Working on a project where I have more or less carte blanche to modify the database schema and object model (nice position to be in. (c:) Suppose I have a trivial inheritance tree like:
class Parent
{
public int ID { get; set; }
}
class Child : Parent
{
// some fields
}
Is it better to have a database schema where the child ID and the parent ID are the same (e.g., parent primary key is IDENTITY(1,1), child primary key is assigned and is a NOT NULL foreign key to the parent table), or should the child table maintain its own primary key and keep its reference to the parent table in another field? What are the considerations to be made in this case? What are the pro's and con's of each approach? NHibernate supports both, right?
I would let the child have it's own id. It'd be useless information but that detriment is far outweighed by the fact that it would be an easily recognizable 1-to-1 relationship rather than a "How the heck does this work?" relationship.
And yes, nHibernate can handle one-to-one relationships.
Related
I am having two classes, like below
Class One
{
ID (PK),
Property 2;
}
Class Two
{
ID (PK),
One_ID (FK),
Nullable_One_ID (FK)
}
While saving I am getting error ' Unable to determine the principal end of the 'x' relationship. Multiple added entities may have the same primary key.'
I tried many combinations WithOutPrincipal and WithOutDependant etc. But no luck, please guide me to the right relationship.
If you are trying to have 1 to 0 or 1 relationship between class one and class two then you need to have primary key and foriegn key same in class 2 and it should be primary key of class one
Class One { ID (PK), Property 2; }
Class Two { One_ID (PK, FK), Nullable_One_ID (FK) }
Your question is a bit unclear, and you might want to provide more detail, but I suspect that you want only one foreign key property on your class two. Depending on how you're creating these objects, this may also be happening because you're trying to reference an id that's 0, because the object has not yet been saved to the database, so it has not been assigned an id.
I've gone through the Entity Framework code-first tutorials and I hate to say but I'm at a loss for how it works. Everything works but I want to know how because everything I know about basic database design tells me it shouldn't. I feel like I'm missing a critical link with how it's creating foreign keys and hope someone can explain it.
I initially copied and pasted a bunch of code-first designs of a simple Parent class with multiple child types. In my child types I had a reference to the virtual Parent and a ParentID reference. I noticed in the database that the value of ParentID was 0 for every single child of type A and B.
However, when loading the data in code and debugging/displaying, entity relationships were correctly maintained.
The code looks like (class names were changed to remove context of what it is):
public class Parent{
public int? ParentID {get;set;}
public virtual ChildA ChildA {get;set;}
public virtual ChildB ChildB {get;set;}
}
public class ChildA{
[Key,ForeignKey(Parent)]
public int ChildAID {get;set;}
public string Field {get;set;}
//public int ParentID {get;set;}
[ForeignKey("ParentID")]
public virtual Parent Parent {get;set;}
}
public class ChildB{
[Key,ForeignKey(Parent)]
public int ChildBID {get;set;}
public string Field {get;set;}
//public int ParentID {get;set;}
[ForeignKey("ParentID")]
public virtual Parent Parent {get;set;}
}
I commented out the ParentID to show explicitly what I was talking about. To test this out, I deleted the column in the database and yet the relationships still work correctly. There are only three tables that relate to this in the database (Parent, ChildA, and ChildB). There aren't any foreign keys, and the parent table doesn't reference the children tables and the children tables don't reference the parent table. When I load them from the DBContext, the mappings correctly load them as I saved them.
What am I missing here? Something somewhere is keeping track of this mapping but I can't tell where. And the fact that it isn't stored as a really basic foreign key in the database concerns me about performance.
What do you mean by There aren't any foreign keys, and the parent table doesn't reference the children tables and the children tables don't reference the parent table. ?
I think you were missing to notice that there are relationship between them.
It's called one to zero-or-one relationship.
Your question is a bit baffling because Entity Framework does store relationships as "really basic foreign keys", so I can't see how you've come to that conclusion.
Commenting out the ParentID to show what your talking about doesn't help much because it should actually have had no effect. That is because when you add the [ForeignKey("ParentID")] attribute to the Parent property, you are telling Entity Framework to put a foreign key in the database named "ParentID" to model the Parent relationship.
You don't need the ParentID integer property in your Entity, but it is usually easier to include foreign keys, and most examples show this.
Now, if you do include ParentID, then you don't need the [ForeignKey("ParentID")] attribute on the Parent property because EF will assume that ParentID is the foreign key for the Parent navigation property because you have followed a standard naming convention.
Also you could try this - remove both the ParentID and the [ForeignKey("ParentID"] attribute and update the database. Now you should find that EF has added a foreign key named "Parent_Id". So foreign keys used always!
The [Key,ForeignKey(Parent)] attribute on your keys looks wrong. The ID isn't a navigation property so you don't need to specify a foreign key for it, so I'm not sure what that is doing (actually, on second thoughts, this may be your problem, I think this is specifying a one to one). That Key attribute is also unnecessary because again you have followed a naming convention.
So in summary, get shot of all your attributes and follow the naming conventions until you need to do something tricky!
The following are two partial tables in which I am trying to define a foreign key relationship.
public class Form
{
[Key, Column("FormID")]
public System.Guid FormGUID { get; set; }
[Column("PatGUID")]
public Nullable<System.Guid> PatientGUID { get; set; }
}
public class Patient
{
[Column("PatGUID")]
public System.Guid PatientGUID { get; set; }
[Key, Column("PatID")]
public int PatientID { get; set; }
}
I've eliminated all but the relevant information, fields, navigations, etc. for this example; hopefully not too much.
We have a table Form, with a FK of PatGUID to a Patient table with field PatGUID.
The Patient table has a PatID int KEY field.
We have requirements to rename our fields for our code first entity models; the relevant fields in this example needing changed is PatGUID being changed to PatientGUID.
The difficulty I am having is trying to define this foreign key using either annotations or fluent.
So the end result I need is:
Primary Key Table: Patient, Field: PatGUID (renamed PatientGUID)
Foreign Key Table: Form, Field: PatGUID (renamed PatientGUID)
This doesn’t seem like it should pose a large problem but with the combination of Patient.PatGUID not being the primary key and the PatGUID fields being renamed to PatientGUID has not enabled the WCF Data Service to properly create a reference with a proper reference thus a proper select/join of:
SELECT … FROM [dbo].[Form] AS [Extent1]
INNER JOIN [dbo].[Patient] AS [Extent2] ON [Extent1].[PatGUID] = [Extent2].[PatGUID]
EF doesn't yet support relationships where the principal's key is not the primary key but some other column with a unique key constraint. It is on the feature request list but neither implemented nor on the road map for the next release (EF 6). If it gets implemented at all (in EF 7 maybe) expect to wait a year or more until it's ready for production.
In your particular model EF doesn't recognize any relationship between Form and Patient at all because Patient.PatientID is marked as [Key], not Patient.PatientGUID, and EF treats Form.PatientGUID as an ordinary scalar property, not as an FK to Patient.
In theory you could fake Patient.PatientGUID as the [Key] property in the model although it is not the primary key in the database if you don't create the model from the database or the database from a code-first model, that is, if you map between model and (existing) database manually. But I am not sure if this wouldn't cause subtle problems anywhere else.
The alternative is to write manual join statements in LINQ if you want to fetch Patients and related Forms. You can then join two entities using arbitrary properties, not only key properties. This is, in my opinion, the cleaner and less "tricky" approach. However, the downside is that you won't have navigation properties - references or collections - between Patient and Form and you can't use features like eager loading (Include), lazy loading or comfortable "dotted path syntax" (like Form.Patient.SomePatientProperty, etc.) in your LINQ queries.
My Order class has:
public int CustomerId { get; set; }
public Customer Customer { get; set; }
Do I really need both properties to make a relation working?
I am not using disconnected entities, I am using code first approach.
According to Julia Lerman's book: Programming Entity Framework: DbContext, the difference lies at the difficulty of updating the navigation property. In page 85, She suggests "If there is one thing you can do to make your life easier in N-Tier scenarios, it’s to expose foreign key properties for the relationships in your model." The book includes samples for both scenarios.
The reason is that including a foreign key property tells Entity Framework to use Foreign Key Association, which is simpler than using the so-called Independent Association when you need to update the relationship, i.e., changing the order from one customer to another in your example. With foreign key association, all you need to do is changing the CustomerId. Without the CustomerId foreign key, you need more steps. The independent association uses the ObjectStateManager that is explained Code First: Independent associations vs. Foreign key associations? The ObjectStateManager is complex and is not even exposed from DbContext API.
Is it possible to pass a reference at load time of a parent to it's children without a relationship back to the parent from the child?
I would prefer to NOT have a mapped property for this purpose (i.e. prefer not to use bi-directional relationships for this purpose).
You could probably do it with a linking table but you'd have to enforce one-to-many via code otherwise it could easily become a many-to-many. The jist of the linking table would be that it keeps the association between the parent and its children, rather than the child object itself.