Dictionary for storing orders - DataStructure - c#

I have some orders coming down the wire quite frequently, I need to store them and build an aggregation out of them. An order will have an ID and there will be an instrument type associated with it. The orders can also have some events attached to it, like say add, update or remove. If it's an update event, then there will not be an instrument type attached with the order, but the order id will be same. For ex: if I have an order for instrument "xyz" with order id 100, later on I can get an event to update the order which has an id 100 by $20, and there will not be an instrument type present with that event (order).
Once I receive an order, I need to build an order book for unique instruments, for example instrument "xyz" should contain all recieved orders for it inside the orderbook.
My question is how efficiently can I store this and what kind of data structure should I use for it?
An Order looks something like this:
public class Order
{
public Order(Action add, int id, string instrument, int price)
}
An Orderbook:
public class OrderBook
{
public string Instrument;
public List<Order> AllOrders;
}
Option 1:
Update a Dictionary<int,OrderBook> when I receive an order, with key as order id, and create an order book for the instrument.
Issue: This will take care of the update events, I can check whether the order already exists, and then update the order book. However an instrument type should only have one order book, and this condition is violated here, as for instrument "xyz" there could be multiple Add orders coming through, and also makes the manipulation difficult.
Option 2:
Update a dictionary of Dictionary<OrderBook, List<int>>, with values as the order id's.
Issue: This will take care of the above issue, however when I get an update event, I'll have to check through every list of values (i.e list of order id's) to see whether the order exists already, since the instrument type is going to be empty and I cannot look by the OrderBook key.
Orders are coming down at real time, and the operation for storing and retrieving has has to be bit more efficient(if not O(1) then O(logn)), is there a better way to structure this please?
NOTE: An OrderBook is an aggregation of all orders for an instrument and will be unique for the instrument. An order will be for an instrument for a particular price, and there will be many orders for the same instrument. I get the orders along with the event from someone else(a third party lib), and I'm responsible for building the orderbook.

I see this issue as combination of two child issues.
You are tracking the OrderID for across the inputs.
You are maintaining unique Orderbook per item.
In such case, I would suggest maintain both the dictionaries
Alternatively, you can convert the List<order> to dictionary <int, order> in orderbook to simplify the search with the orderbook.
For the option 1, you mentioned
However an instrument type should only have one order book, and this
condition is violated here
You are not going to have multiple orderbooks, but maintaining the reference of the same order book across the dictionary entries.

Try this.
public class Order
{
public Action Action { get; set; }
public int Id { get; set; }
public int Price { get; set; }
public Order(Action add, int id, int price){
//Initialize
}
}
public class Instrument
{
public string InstrumentName { get; set; }
public Dictionary<int, Order> OrderBook { get; set; }
public Instrument(string instrument)
{
InstrumentName = instrument;
//OrderBook = new List<Order>();
}
public void AddOrder(Order order)
{
//Check order exist condition
OrderBook.Add(order.Id, order);
}
}
Then use List<Instrument>
I guess it should work for you. Let me know if any issue in this.

Related

Should I use a set to prevent items being added more than once to the collection by mistake?

Please see the code below:
public class Customer
{
private readonly IHashSet<Order> _orders = new Set<Order>();
public string FirstName { get; set; }
public string LastName { get; set; }
public string Province { get; set; }
public IEnumerable<Order> Orders
{
get { foreach (var order in _orders) yield return order; }
}
internal void AddOrder(Order order)
{
_orders.Add(order);
}
}
I am trying to decide whether the _orders property should be a List (which I would normally use) or a Set. The only reason a duplicate order would be added is if the client code added a duplicate by mistake. Does that warrant the use of a Set? Is that a valid use case for a Set?
Sure, this is a valid use case, if duplicate orders are not allowed.
Since you expose IEnumerable<Order> instead of IList<Order> you don't seem to be interested in keeping the insertion order, or let the caller use it like a list or array. So a HashSet<T> is perfect here. The database is the best place to ensure that no duplicates are added, but it's not wrong to check that also at client-side. On this way you can handle bugs early and report them in your logs.
public class Customer
{
private readonly HashSet<Order> _orders = new HashSet<Order>();
public IEnumerable<Order> Orders => _orders;
// ...
internal void AddOrder(Order order)
{
_orders.Add(order);
}
}
Note that you should override Equals+GetHasCode in Order, implement IEquatable<Order> or pass a custom IEquatable<Comparer> to the HashSet constructor.
You have tagged your question with domain-driven-design tag, so the answer should be given in this context.
There is a rule in DDD called "make explicit what is implicit". If you don't want to have duplicates in your orders, in my opinion you should add some simple code that makes this rule explicit. It can be just a simple vetoIfOrderIsDupicated private method or something similar. It will give you a chance to communicate your team mates (or even you in the future) that there is a rule which should not be broken. If you just change this collection to Set, it doesn't carry any information WHY this is a Set. In the future someone from your team (or you personally) will refactor this code for example from performance perspective and will change Set to some high performance List, but will loose the rule.
So answering your question: I recommend to make the rule explicit. And collection can be Set if you want.
Additionally and not correlated to question, I don't know your domain, but it seems to me, that Order is another Aggregate Root. If yes, you shouldn't reference both Aggregate Roots. Instead you should reference IDs of AggR. So _orders should be collection of OrderID.

An alternative lookup table approach needed to make C# models more generic

I currently have the following Models in my EF Code First MVC project (edited for brevity):
public class Car
{
public int Id { get; set; }
public string Descrip { get; set; }
// Navigation Property.
public virtual CarColour CarColour { get; set; }
... + numerous other navigation properties.
}
public class CarColour
{
public int Id { get; set; }
public string ColourName { get; set; }
}
The CarColour table in the DB contains many rows.
In my project, I have about 10 of these sorts of tables, which are essentially lookup tables.
Rather than have 10 lookup tables (and 10 corresponding 'hard' types in code), I was tasked with implementing a more re-usable approach, instead of having loads of lookup tables, specific to Car (in this example), along the lines of having a couple of tables, one of which may hold the item types (colour, fuel-type etc.) and one which contains the various values for each of the types. The idea being that our model will be able to be re-used by many other projects - some of which will have potentially hundreds of different attributes, and as such, we won't want to create a new Class/Type in code and generate a new lookup table for each.
I am having difficulty in understanding the c# implementation of this sort of approach and hope someone may be able to give me an example of how this can be achieved in code, more specifically, how the above models would need to change, and what additional classes would be required to accomplish this?
your base entity must implement INotifyPropertyChanged and make it generic:
public virtual CarColour CarColour {
Get { return this.carColour; }
Set {
this.Carcolour; = value
OnPropertyChanged("CarColour");
}
}
For more info see :
patterns & practices: Prism in CodePlex.
http://compositewpf.codeplex.com/wikipage?title=Model%20View%20ViewModel%20(MVVM)
Greetings
Bassam
This is not necessarily specific to EF but I've been down this road and didn't really enjoy it.
I wanted to use a single table to represent 'generic' information and while I thought it was smart, it soon showed it's limitations. One of them being the complexity you need to introduce when writing queries to extract this data if you're performing more than just 'get colours for this car'.
I'd say, if your data is simple key/value and the value type is always going to be the same then go for it, it might even be worth having this a mere 'meta-data' for an object:
public class Car
{
public int Id { get; set; }
public string Descrip { get; set; }
public MetaData CarColours { get; set; }
}
public MetaData : Dictionary<int, string>
{
public MetaData(int group){}
}
Hypothetical table:
TableMetaData(int metaGroup, int metaId, string metaValue)
If you're hoping to store different types as your value and may need to perform joining on this data - avoid it and be a bit more specific.

Data structure with user specified order

I have this class :
public class Item
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
I want to store instances of Item in a list, and keep it ordered like the user has ordered them (Likely to be in a GUI with up-down arrows while selecting an Item)...
Should I be adding an order member to my Item class, or is there a specific datastructure that can keep an arbitrary user-specified order.
Note: I'm going to use this to keep a list of items, in the order a person has seen them, walking in a store.
If you intend to persist the list to a database then you may want to include an Order property in your Item class; databases such as SQL Server do not guarantee the order of the result set.
List/Array/Collection are names for ordered sequence of items.
List<Item> is enough to keep items in particular order. Note that re-ordering items will be "slow" ( O(n) ) operation in this case to move single item in new place. If you just need Add regular List<T> is probably the easiest choice that does not require any additional fields.

C Sharp Object creating and referencing only 1 object in another class

I need to implement 1..* and 1..1 relationships in a store scenario application.(Classes: Member, Order, OrderLine, Product, Program, User) How do i go about a 1 user only having 1 Order that can have many OrderLines (preferably using a List structure?
This is my User class:
namespace ConsoleApplication1
{
public class User
{
private string ffName;
private string llName;
private int id = 0;
//Constructor
public User(string firstName, string lastName)
{
fName = firstName;
lName = lastName;
}
public User() {}
//Overrides
public override bool Equals(object obj)
{
return obj.ToString() == this.ToString();
}
public override int GetHashCode()
{
return this.ToString().GetHashCode();
}
public override string ToString()
{
string myUser;
myUser = string.Format("First Name: {0}; Last Name: {1}", fName, lName);
return myUser;
}
// Properties
public string fName
{
get
{
return ffName;
}
set
{
ffName = value;
}
}
public string lName
{
get
{
return llName;
}
set
{
llName = value;
}
}
}
}
You can have an Order class and an OrderLine class. The Order class will have a List of OrderLines and the User class can have a Order member.
Something like:
public class User
{
private string ffName;
private string llName;
private int id = 0;
private Order order = null;
//Constructor
public User(string firstName, string lastName)
{
fName = firstName;
lName = lastName;
}
...
}
public class Order
{
List<OrderLine> orderLines = null;
}
public class OrderLine
{
}
You have to implement the Order and the OrderLine class as:
class OrderLine
{
//some code
}
class Order
{
List<OrderLine> lstOrderLine;
//some code
}
Then add the Order class to your user class.
Edit: Removed snarkyness and attitude :)
First you need an order (hint you are going to need a class for that). Now the order needs to be attched to a user. So add a field of type User. That takes care of one order one user. (Note that a user can make more than one order)
So now you order is missing lines. Add another member variable that is a list of line types. Now in your order you need to add methods to add, remove and query order lines.
Edit: The question was raised what was meant by "add a field". Add a field means add a property or private member. When you are doing this you are doing the technical term of composition. Composition is commonly explained as a "has a" relationship. So an order "has a user" and "has a list of order lines"
Class User()
{
public string firstName { get; set; }
public string lastName {get; set; }
public int id { get; set;}
}
Class OrderLine()
{
}
Class Order()
{
private List<OrderLine> orderLines;
public User submitter { get; set;}
public Order()
{
orderLines = new List<OrderLine>();
}
public void AddOrderLine(OrderLine newOrderLine)
{
this.orderLines.Add(newOrderLine);
}
public IList<OrderLine> GetOrderLines()
{
return this.orderLines;
}
}
Example
User customer1 = new User();
// Initialize customer1 values...
Order someOrder = new Order();
someOrder.submitter = customer1;
someOrder.AddOrderLine(new OrderLine());
EDIT: Changed Member class to User class
Your most recent comment cleared up your question:
Its not hard to create each one i just dont understand how to get the relationship to work with 1..* or 1..1. If i create an Order i can always create another order
So, let's talk about the types of relationships.
Relationship types
Relationship types don't talk about absolute numbers of entities in the system. They just talk about numbers of entities in relation to other entities.
1:1 Relationship
This means that the two entity types must exist in pairs. If one entity of type A exists, then only one entity of type B can exist. For example, your User and Order. An order can't exist without a User, and a User can only have one Order. This doesn't mean there is only one User - there could be 42 users. This just means that if an Order exists, a User must also exist, and that the User can only have one Order.
There is a strict and less strict version of this. Technically, I just described something like a 1:{0 or 1} relationship. In a real 1:1 relationship you would require that the Order exists if the User exists. Neither could exist if the other didn't exist. However this constraint is usually relaxed when talking about relational databases (but only in one direction - in this case you still can't have an Order without a User).
You can model this relationship with code like this:
public class User
{
public Order Order { get; set; }
}
public class Order
{
// You could put a reference here back to the User if you want...
}
Note that it is a bit weird to only support only one Order for a User. It makes more sense to make it 1:*. But if that is a requirement of your assignment, then this is how you'd model it.
1:* Relationship
This is similar to the 1:1 relationship. But it relaxes some of the restrictions so that if an entity of type A exists, then any number (including zero) of type B can exist. The example is the Order and OrderLine. Again, there is no restriction on how many of either entity type exist. There could be 57 orders in the system. You just can't have an OrderLine without an Order, and there could be multiple OrderLines per Order.
You can model this relationship with code like this:
public class Order
{
public List<OrderLine> OrderLines { get; set; }
}
public class OrderLine
{
// You could put a reference here back to the Order if you want...
}
Enforcing relational concepts in code
I can't speak for your assignment, so make sure you back up what I am saying here against what your assignment requires.
You should not try to enforce basic relational concepts like these in code. The database is better at it, has better (declarative) language to describe the relationships, and is going to be your ultimate source of data for the system.
Instead, you should just do a soft model that follows the relationships (as the code samples above do), and let the database do the real policing of those constraints.
Examples:
You should not try to restrict construction of Order types in code, and you shouldn't require a User to exist to construct an Order (as code entities).
You should not require an Order to exist to create an OrderLine (as code entities).
Trying to put these sorts of restrictions in code buys you nothing. When you persist the entities to the database, the database will ensure these relationships for you (assuming you've set it up correctly, which you will learn to do). Your error will be caught, and you'll learn habits that avoid these types of errors very quickly.
Trying to put these sorts of restrictions in code hurts you. It will be harder to write your program, and it will be harder to write unit tests for your code.
For example, consider an algorithm or test that compares OrderLine values. Maybe you want it to compare to a hypothetical OrderLine. If you had relational restrictions in place in your code, you'd also have to create a hypothetical Order and User. Would you also compare the hypothetical User and Order to the real ones? What if your algorithm shouldn't care what User or Order it originated from? If you're not going to compare them, why bother creating them to begin with?
So: Don't worry about it. Softly model your relationships so that it is easy to navigate between your objects, and let the database do your strict relationship validations for you.

Should I incorporate list of fees/discounts into an order class or have them be itemlines

I have no other developers to ask for advice or "what do you think - I'm thinking this" so please, if you have time, have a read and let me know what you think.
It's easier to show than describe, but the app is essentially like a point of sale app with 3 major parts: Items, OrderItems and the Order.
The item class is the data as it comes from the datastore.
public class Item
: IComparable<OrderItem>, IEquatable<OrderItem>
{
public Int32 ID { get; set; }
public String Description { get; set; }
public decimal Cost { get; set; }
public Item(Int32 id, String description, decimal cost)
{
ID = id;
Description = description;
Cost = cost;
}
// Extraneous Detail Omitted
}
The order item class is an item line on an order.
public class OrderItem
: Item, IBillableItem, IComparable<OrderItem>, IEquatable<OrderItem>
{
// IBillableItem members
public Boolean IsTaxed { get; set; }
public decimal ExtendedCost { get { return Cost * Quantity; } }
public Int32 Quantity { get; set; }
public OrderItem (Item i, Int32 quantity)
: base(i.ID, i.Description, i.Cost)
{
Quantity = quantity;
IsTaxed = false;
}
// Extraneous Detail Omitted
}
Currently when you add fees or discounts to an order it's as simple as:
Order order = new Order();
// Fee
order.Add(new OrderItem(new Item("Admin Fee", 20), 1));
// Discount
order.Add(new OrderItem(new Item("Today's Special", -5), 1));
I like it, it makes sense and a base class that Order inherits from iterates through the items in the list, calculates appropriate taxes, and allows for other Order-type documents (of which there are 2) to inherit from the base class that calculates all of this without re-implimenting anything. If an order-type document doesn't have discounts, it's as easy as just not adding a -$ value OrderItem.
The only problem that I'm having is displaying this data. The form(s) that this goes on has a grid where the Sale items (ie. not fees/discounts) should be displayed. Likewise there are textboxes for certain fees and certain discounts. I would very much like to databind those ui elements to the fields in this class so that it's easier on the user (and me).
MY THOUGHT
Have 2 interfaces: IHasFees, IHasDiscounts and have Order implement them; both of which would have a single member of List. That way, I could access only Sale items, only Fees and only Discounts (and bind them to controls if need be).
What I don't like about it:
- Now I've got 3 different add/remove method for the class (AddItem/AddFee/AddDiscount/Remove...)
- I'm duplicating (triplicating?) functionality as all of them are simply lists of the same type of item, just that each list has a different meaning.
Am I on the right path? I suspect that this is a solved problem to most people (considering that this type of software is very common).
I'll point you to a remark by Rob Connery on an ALT.net podcast I listened to not long ago (I'm not an ALT.net advocate, but the reasoning seemed sound):
What does make sense to a "business user" (if you have any of those around).
As a programmer, you're gonna want to factor in Item, Fee, Discount etc, because they have similar attributes and behaviors.
BUT, they might be two totally separate concepts in terms of the model. And someone is gonna come at a later time, saying "but this makes no sense, they are separate things, I need to report on them separately and I need to apply this specific rule to discounts in that case".
DRY does not mean limiting your model, and you should keep that in sight when factoring behavior via inheritance or anything like that.
The specific example that was used in that case was that of the shopping cart. The programmer's natural idea was to use an order in an uncommited state. And it makes sense, because they look exactly the same.
Except that they are not. It makes no sense to the client, because they are two separate concept, and it just make the design less clear.
It is a matter of practices, taste and opinion though, so don't blindly follow advice posted on a web site :)
And to your specific problem, the system I work with uses items, fees, line-item discount (a property of the item) and a global discount on the order (though it's not an order, it's POS receipt but it does not really matter in that case).
I guess the reason is that, behind those concepts, Items are specific instances of inventoried pieces, they impact stock quantities, they are enumerable and quantifiable.
Fees are not. They do not share most of the attributes.
It might not matter in your case, because your domain seems much more limited than that, but you might want to keep those issues in mind.
Effectively, I'd look at your design in the details and try to figure out where the behaviors lie; then extract any commonalities in those behaviors to a distinct interface and make sure that applies to your design.
To wit; Fees may have associated validation behaviors associated with them. Let's say you add a Fee to any Order which has 20 items or more (just a random example, run with me on this one). Now, when you add the 20th item, you may want to add that Fee to the Order, but there's a problem; when you remove an item from your order, do you want to have to check every time to see if you need to remove that Fee from your order? I doubt it; the implication here is that there is a behavior that is associated with the Fees / Discounts that essentially makes them an entirely different class of things.
I'd look at it this way; categorize Fees and Discounts as "Special" things, and then create an "ISpecial" interface from which both Fees and Discounts inherit. Extract any common functionality to the ISpecial interface (for example, "Validate"). Then have your Order implement the ISpecial (or whatever) interface.
In that way, you can define the specific Fee.Validate() behavior and the Discount.Validate behavior, and have the operate properly thanks to the magic of polymorphism (foreach of m_specialCollection .validate those). In that way, as well, you can easily extend the Special interface for anything else that might be necessary (say, Taxes).
I think the core of the problem that you're facing here is that you've implemented OrderItem as a subclass of Item, and now you're discovering that this really isn't always appropriate.
Given what you describe, here's how I'd try implementing this:
Create an Order class that implements public properties for every single-valued data element that you want to expose to data binding: order number, date, customer, total fees, total discounts, etc. It sounds like you may be needing to display specific fees/discounts as single values; if so, implement public properties for those.
Create an abstract OrderItem class that implements public properties for every data element that you want to bind to in the grid, and for every data element that you want to sort the items on. (You could also make this an IOrderItem interface; it really depends on whether or not there are going to be methods common to all order items.)
Create subclasses of OrderItem (or classes that implement IOrderItem) for the specific kinds of line item that can appear on an order: ProductOrderItem, FeeOrderItem, DiscountOrderItem, etc.
In your implementation of ProductItem, implement a property of type Item - it'd look something like:
public class ProductItem : OrderItem
{
public Item Item { get; set; }
public string Description { get { return Item.Description; } }
public int Quantity { get; set; }
public decimal Amount { get { return Item.Price * Quantity; } }
}
Implement a property of type IEnumerable<OrderItem> within Order for storing all of the line items. Implement an AddItem method for adding OrderItems, e.g.:
public void AddItem(OrderItem item)
{
_Items.Add(item); // note that backing field is a List<OrderItem>
}
which you can call pretty simply:
Order o = new Order();
o.AddItem(new ProductOrderItem { Item = GetItem(1), Quantity = 2 });
o.AddItem(new FeeItem { Description = "Special Fee", Amount = 100 });
o.AddItem(new DiscountItem { DiscountAmount = .05 });
Write implementations of those single-valued fields that need to extract values from this list, e.g.:
public decimal TotalFees
{
get
{
return (from OrderItem item in Items
where item is FeeItem
select item.Amount).Sum();
}
}
You can come back later and optimize these properties if necessary (e.g. saving the computation once you've done it once).
Note that you could also restrict AddItem to adding ProductItems, and use other methods in the Order to add other types of items. For instance, if an order can have only one discount amount:
public void SetDiscountAmount(decimal discountAmount)
{
DiscountOrderItem item = _Items
.Where(x => x is DiscountOrderItem)
.SingleOrDefault();
if (item == null)
{
item = new DiscountOrderItem();
_Items.Add(item);
}
item.DiscountAmount = discountAmount;
}
You'd use this approach if you wanted to display the discount amount in the appropriate place in the grid of order items, but also wanted an order's discount amount to be a single value. (It's arguable that you might want to make DiscountAmount a property of the Order, create the DiscountOrderItem in its setter, and have DiscountOrderItem get its Amount from Order.DiscountAmount. I think both approaches have their pros and cons.)
One option is to add a ItemType attribute to OrderItem
enum ItemType
{
Item,
Fee,
Discount
}
Now you could in your order class have:
public IList<OrderItem> Fees
{
get
{
return _items.Find(i=>i.ItemType==ItemType.Fee);
}
}
Now you can still keep your single list and avoid the extra interfaces. You could even have a method like IList GetItems(ItemType type).
One other thought is your current design doesn't allow for a discount of a %. Today you get 10% off. This might not be a requirement, but one option to avoid the application having to calculate this is to seperate the items from the discounts.
The discounts could even become more of rules, if I order 10 items take 5% off.

Categories