Entity Framework Relationship Matching - No Foreign Keys In DB - c#

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!

Related

Why is there duplication of references in code-first EntityFramework?

In learning the code-first EntityFramework methodology, I don't understand why you need "duplicate" references between two data sets, i.e. a Navigation Property as well as an explicitly defined foreign key.
For example, an "Enrollment" has a one-to-one relationship with a "Course" and a "Student". In the student's model class, you define a navigation property like so:
public virtual ICollection<Enrollment> Enrollments { get; set; }
This will create a column for foreign keys to Student in the Enrollments table if you do a migration.
But in the "Enrollment" class, you also have a property representing the Student's foreign key like so:
public int StudentID { get; set; }
So my question is: what is the purpose of defining this foreign-key relationship on both ends? I have seen it done where only the Navigation Property is defined on one end, and also where the relationship is only defined on the other end. What is the reason for both?
The navigation property allows you to access the collection of referenced entities when you query the entity.
The single ID property is the reference to the column that actually holds the value of the foreign key reference.

In MVC model, what is the significance of defining a key field as Id or EntityNameId?

In MVC model, we have to declare a key field as Id or EntityNameId. What is the significance of it? Can I declare a key field with any name I wish ?
Assuming this is for Entity Framework, You can decorate any field within your models with the [Key] attribute.
public class Student {
[Key]
public int StudentRegNumber { get;set; }
}
However I am sure it's best practice to keep Id in the name for use in EntityFramework simply because it does all the property mapping for you. If you want to go a step further and manage this primary key yourself (not recommended) and make it not auto increment you can use this attribute as well
[DatabaseGenerated(DatabaseGeneratedOption.None)]
But ideally, as I mentioned before you are going to want to keep Id in the name, so let's go with this instead.
public class Student {
public int StudentId { get; set; }
public int RegNumber { get; set; }
}
Since EF is smart enough to map the Key automatically utilise that sweet sweet power!
Extended
Mackan suggested explaining the importance. If we start changing our Primary Key names to not follow the convention of suffixing then name with 'Id' and rather just leaving them to be anything, it can become confusing when building up queries later on, or doing Joins on your datasets etc.
However it's best to make a choice and stick to one type of naming convention, there is a debate (1 & 2) as to whether it's actually bad practice to do TableNameId instead of just Id, however that is for you to decide what works best for you, but I would recommend away from just naming them something unrelated to their primary purpose; the unique identification of that record.
Further Reading
Data Annotations in Entity Framework
Entity Framework Code First Conventions
Entity Framework Code first relies on every entity having a key value that it uses for tracking entities. One of the conventions that code first depends on is how it implies which property is the key in each of the code first classes. That convention is to look for a property named “Id” or one that combines the class name and “Id”, such as “BlogId”. The property will map to a primary key column in the database. See link https://msdn.microsoft.com/en-us/data/jj591583.aspx

Entity framework navigation properties naming convention

I have two tables named as Profile and ProfileHistory.
Each record in ProfileHistory has to belong to a profile in Profile table, so there is a foreign key relation between two tables. Besides, in ProfileHistory table, there is a column named as ManagerId which also relates to Profile table with foreign key relation.
Profile table structure
Id int primary key
....
....
ProfileHistory table structure
Id int primary key
ProfileId int foreign key to Profile table
ManagerId int foreign key to Profile table
....
My question is:
Since currently I only know this, I am creating my entity model from database.
Model and therefore entity classes are created with navigation properties in
ProfileHistory entity like following:
public virtual Profile Profile { get; set; }
public virtual Profile Profile1 { get; set; }
It is so confusing. Because it is not clear which navigation property for which relation.
Even it is worse if I have more relations between two tables. navigation property names are becoming Profile, Profile1, Profile2, etc.
I was expecting to have the name of the navigation properties related with its foreign key relations.
How can I make my navigation property names something that related to its foreign key relation, in my case "from Profile1 to ProfileManager" ?
Thank in advance for your kind helps.
Muharrem
You can always rename the properties in model diagram. The name can be found in Properties window when you click on a navigation property.
I haven't tested it, but you can map a property to a column using an attribute:
[Column(“BlogDescription", TypeName="ntext")]
public virtual Profile Profile { get; set; }
[Column("Profile1", TypeName="int")]
public virtual Profile ProfileManager { get; set; }
Change the type and the name of the column as it is in the database.
The way I usually solve this is to add properties through partial classes that better represent what I'm after. This way if I need to delete the entity from the diagram and re-add it, I don't lose any renamed columns from the model.
The downside to this is that you need to remember that you cannot use them in Queries because EF won't know how to translate it into a SQL query. But if you've already got your Profile object, it's a lot easier to access myProfile.Manager than myProfile.Profile1.
So, for example, if EF created this for you:
public partial class ProfileHistory
{
public virtual Profile Profile { get; set; }
public virtual Profile Profile1 { get; set; }
}
I would end up creating a partial class like this to re-map the columns:
public partial class ProfileHistory
{
public Profile Manager
{
get
{
return this.Profile1;
}
set
{
this.Profile1 = value;
}
}
}
I did face the same problem some time ago. Well, it is even bigger then just confusing names. If you have navigation properties to another table, like Profile, Profile1, Profile2, next you delete/edit the corresponding foreign keys you may end up having those mixed. And if you used EntitySQL to query data you'll end up having bugs because of incorrect data retrieved/wrong table join conditions...
What I did was changing the t4 template and modified the way properties are generated. When property code text is being written you have the information about association and foreign key related to it. Foreign key names are unique in database and I named those with following pattern
FK_[Table]_[Meaning]
...
FK_ProfileHistory_InitialProfile
FK_ProfileHistory_UpdatedProfile
Next, having this information, I named the properties with the [Meaning] part of the foreign key name.

Creating entity relationship with renamed fields and non-primary key in primary table

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.

ID's on parent and child classes in NHibernate

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.

Categories

Resources