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

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.

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.

dapper PropInfo Setter for inherited EntitySet from abstract class reference is null

I am trying to replace a nasty LINQ 2 SQL hit with some dapper queries to improve performanace. In doing so I have to weave a bunch of different objects together in order to create the big object required to hold all the information I need for ASN information.
The current problem I am having is with an abstract class Orders, this class is implemented by two seperate classes AutionOrder and MerchantOrder using a discriminator property.
Since I cannot use dapper to create a object that is an abstract class I am instead using one of the public classes. however when it goes to build the object it is failing inside of GetSettableProps it is finding the proper DeclaringType but the GetProperty method is returning null when it is looking for an property that is internal or is an EntitySet. I've tried to hack around it using t.BaseType.GetProperty as well as p.GetAccessors().First().GetBaseDefinition().DeclaringType.GetProperty(p.Name).GetSetMethod(true) with no success.
dummy objects:
Order
OrderID, Name, Address, RowVersion(internal), Shipments(EntitySet),OrderDetails(EntitySet), Customer(EntityRef)
Shipment
ShipmentID, OrderID, TrackingNumber
OrderDetails
OrderDetailID, OrderID, Product, QTY, Price
Customer
CustomerID, Name,
For this particular SQL hit I am trying to grab some of the 1 to 1 relationship mappings I need.
SELECT o.* from Orders as o left join Customers as c on o.CustomerID = c.CustomerID where o.OrderID in (1,2,3);
This is what I am using to utilize dapper and let it do it's magic:
using (var connection = new SqlConnection(_ConnectionString))
{
connection.Open();
results = connection.Query<MerchantOrder, MerchantCustomer, MerchantOrder>(sql.ToString(),
(o, c) => { o.Customer = c; return o; },
splitOn: "CustomerID");
}
If I change Order to be a public class this problem goes away though, but this is not a desired side-effect. It is failing when trying to set the propInfo for RowVersion - switching this to public instead of internal solved this problem - although not desired. But then it fails when it is trying to create the Shipments objects for Order. Again none of this is an issue when Order is a public class.
Also I am doing separate queries to pull in Many to one relationships such as Shipments to Orders and OrderDetails to Orders and normalizing the results into a proper Order Object.
MerchantOrder is pretty much an empty class with no real special logic. The discriminating different here is just how we end up finding the CustomerID which is abstracted away prior to the actual SQL hit anyway.
Also I am using the latest version of dapper as of 12/20/2011.
I really like dapper, but this problem is making my head asplode - so thanks for the help!
This was a bug, that is now fixed in trunk:
public class AbstractInheritance
{
public abstract class Order
{
internal int Internal { get; set; }
protected int Protected { get; set; }
public int Public { get; set; }
public int ProtectedVal { get { return Protected; } }
}
public class ConcreteOrder : Order
{
public int Concrete { get; set; }
}
}
// http://stackoverflow.com/q/8593871
public void TestAbstractInheritance()
{
var order = connection.Query<AbstractInheritance.ConcreteOrder>("select 1 Internal,2 Protected,3 [Public],4 Concrete").First();
order.Internal.IsEqualTo(1);
order.ProtectedVal.IsEqualTo(2);
order.Public.IsEqualTo(3);
order.Concrete.IsEqualTo(4);
}
One side note is that, by design, we do not set private fields or properties in the base classes. The behaviour can be magical and not consistent.
Eg:
class A { private int a {get; set;} }
class B : A { private int a {get; set;} }
class C: B {}
// What should "select 1 a" do? Set it on A? Set it on B? Set it on Both? Set it on neither?
We went with "set it on neither"
I think is not possible (because of the abstract class) without modifying your code.
I had a similar problem and ended up creating a new object private to the assembly where I have my repositories that derived from the abstract base class.
This class is not abstract and only visible to the repository class that stores the data, this class had all the required methods for the actual table.

Possible ways to return a subset of data from Repository<T>?

Let's say I need to display a list of customers, but only want to display the Name and somehow associate the key to the name within a list control.
It would probably be costly to retrieve the entire list of customers and all it's properties. In this scenario, would it be better to create another class with the properties that are required (in this case Id and Name)?
A basic implementation could look like this:
public class Customer {
public int Id { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public int Age { get; set; }
.....
}
public class CustomerListView {
public int Id { get; set; }
public string Name { get; set; }
}
public interface IRepository<T> {
public T Find(int id);
public IEnumerable<T> FindAll();
....
}
public class Repository<T>: IRepository<T> {
....
}
public class CustomerRepository: Repository<Customer> {
public IEnumerable<CustomerListView> FindAllListView();
}
Would this approach be appropriate? What other options would there be?
In order to achieve such goals, I create a simple 'View' class, for example CustomerView, which just contains the properties that are needed to display an overview.
My Repository then has a method which returns a collection of these CustomerView objects.
I mostly use NHibernate in my projects. Nhibernate allows you to use 'projections'.
So, what I do in my repository is this:
(note that the code below is just some pseudo-code; it won't compile).
public IList<CustomerView> GetAllCustomers()
{
ICriteria crit = _session.CreateCriteria (typeof(Customer));
crit.AddProjection ( ... );
crit.SetResultTransformer (new EntityToBeanTransformer(typeof(CustomerView));
return crit.ToList();
}
In fact, it comes down to this: I tell my O/R mapper that it should query Customers, but that it should return entities of type 'CustomerView'.
In the defintion of the projection, I also define which properties of the Customer class map to which properties of the CustomerView class.
Then, the O/R mapper is smart enough to generate a very simple query, which only retrieves those fields that are required to populate the CustomerView class.
For instance, the query that is executed can be as simple as:
SELECT customerid, customername FROM tblCustomer
If you use IQueryable as your return instead of IEnumerable than there is no cost of doing:
CustomerRepository().GetAll().Find(1) because AsQueryable doesn't actually execute until you request data. That means LINQ can optimize it out to a:
SELECT .... FROM .... WHERE ID = 1 instead of
GET EVERYTHING. FIND WHERE THE ID = 1
See this post for an explanation:
Why use AsQueryable() instead of List()?
Using this approach you could create an anonymous class and futher narrow down the data going over the wire to just what you want. That way the query generated by LINQ is optimized to the fullest.
If you have to retrieve the list form a Database then your proposal makes some sense but I would look into a Linq and anonymous type solution.
If the list of Customers already exists in memory then there there are no savings.
You could combine the techniques used by Nissan and Frederik (anonymous types and NHibernate) by using Linq-to-NHibernate.
Item #31 in Bill Wagner's More Effective C# says "limit type scope by using anonymous types", and I agree. BTW, I recommend the whole book.

DDD: Enum like entities

I have the following DB model:
**Person table**
ID | Name | StateId
------------------------------
1 Joe 1
2 Peter 1
3 John 2
**State table**
ID | Desc
------------------------------
1 Working
2 Vacation
and domain model would be (simplified):
public class Person
{
public int Id { get; }
public string Name { get; set; }
public State State { get; set; }
}
public class State
{
private int id;
public string Name { get; set; }
}
The state might be used in the domain logic e.g.:
if(person.State == State.Working)
// some logic
So from my understanding, the State acts like a value object which is used for domain logic checks. But it also needs to be present in the DB model to represent a clean ERM.
So state might be extended to:
public class State
{
private int id;
public string Name { get; set; }
public static State New {get {return new State([hardCodedIdHere?], [hardCodeNameHere?]);}}
}
But using this approach the name of the state would be hardcoded into the domain.
Do you know what I mean? Is there a standard approach for such a thing? From my point of view what I am trying to do is using an object (which is persisted from the ERM design perspective) as a sort of value object within my domain. What do you think?
Question update:
Probably my question wasn't clear enough.
What I need to know is, how I would use an entity (like the State example) that is stored in a database within my domain logic. To avoid things like:
if(person.State.Id == State.Working.Id)
// some logic
or
if(person.State.Id == WORKING_ID)
// some logic
Your proposed structure seems fine. (Terminology digression: since State has an ID, it's not a Value Object, but rather an Entity.)
Enums are a code smell, so don't attempt to go that route. It's much more object-oriented to move the behavior into the State object using the State pattern.
Instead of having to write
if (person.State == State.Working)
// do something...
all over your code, this would allow you to write
person.State.DoSomething();
That's much cleaner, and will allow you to add new States if need be.
A previous question of mine unearthed some useful links that I suspect are pertinent to your question, in particular Jimmy Bogard's discussions of Enumeration Classes.
It's a common practice to include an 'Unknown' element with value 0 in an enum. You can do this and use it for the New state if you really want to.
But what you are describing is business logic... setting a state after creating a new object should then happen in the business logic layer, not inside the class itself.
You want to create a factory method that will instantiate the appropriate state class needed, based on the value stored.
something like
public static State GetStateByID( StateEnum value)
{
if(value.Invalid)
throw new Exception();
switch(value)
case State.Working
return new WorkingState();
case State.somethingelse
return new somethingelseState();
case State.something
return new somethingState();
case State.whatever
return new whateverState();
}
When using enums always try to use 0 as Invalid. Under the hood an enum is a value type, and an unassigned int is always 0.
It is common to use a factory, such as this, in conjunction with the state pattern.
So when you read your stored integer value from the database you can cast the int to the enum and call the factory with it to get the appropriate State object.
I personally think it's a mistake to program against IDs. Instead, I would amend your table to the following:
**State table**
ID | Desc | IsWorking | IsVacation
-----------------------------------------------------------
1 Working True False
2 Vacation False True
I would then use these attributes to make business decisions on such as:
public void MakeDecisionOnState(State state)
{
if (state.IsVacation)
DoSomething();
if (state.IsWorking)
DoSomethingElse();
}
Or by being even more clever, use the factory pattern to create the correct instance based on these attributes:
public abstract class State
{
public Guid Id { get; set; }
public string Description { get; set; }
public abstract void DoSomething();
}
public class WorkingState : State
{
public override void DoSomething()
{
//Do something specific for the working state
}
}
public class VacationState : State
{
public override void DoSomething()
{
//Do something specific for the vacation state
}
}
public class StateFactory
{
public static State CreateState(IDataRecord record)
{
if (record.GetBoolean(2))
return new WorkingState { Id = record.GetGuid(0), Description = record.GetString(1) };
if (record.GetBoolean(3))
return new VacationState { Id = record.GetGuid(0), Description = record.GetString(1) };
throw new Exception("Data is screwed");
}
}
Now you've eliminated the if/switch statement, and your code could simply be:
state.DoSomething();
The reason why I do this is that often these types of entities can be configured by the customer, i.e. they may not want to have some of the states active in the system, or they may wish to term them something else. By programming against the attributes the customer can delete / edit the records as they please and even if that process generates new ID's it doesn't affect the system, they just need to set the attributes.
In my opion the domain layer has to be seperated from the DB model / ERM design. I had trouble understanding your final suggestion for the State class. IMHO this is not a good thing for establishing a common language which is one of the main purposes of DDD.
I would go for a simpler design. The state belongs to the Person class. I would include it in the class.
public class Person
{
public int Id { get; }
public string Name { get; set; }
public PersonState State { get; set; }
}
The state itself seems to have defined values (I assume a person is an employee in your context) which don't change very often. So I would model it as enum and treat it as a data type.
enum Days {Working, Vacation};
This is a simple to understand design in my opinion. The mapping to the ERM design belongs IMHO in the persistence layer. There the enum has to be mapped to the key of the state table. This could be done using an aspect to keep the original domain model clean.

Categories