How to make a manual relationship relationship without using fluentapi - c#

I don't like to use the fluent api in an entity framework, instead, I would prefer to use a manual way such as the following:
[Key]
public int id { get; set; }
but, how can I make a foreign key using this manual way above?

You can use [ForeignKey("[Name of column]")] anntribute. For examle:
public class Student
{
public int ID { get; set; }
public string Name { get; set; }
public int StandardRefId { get; set; }
[ForeignKey("StandardRefId")]
public Standard Standard { get; set; }
}
public class Standard
{
public int ID { get; set; }
public string Name { get; set; }
public ICollection<Student> Students { get; set; }
}
For more information see for examle EF Code Firs Foreign keys

Related

Entity Framework Core One-to-One, Not Unique

Given two tables, TrackingTag and TrackingTagStatusUpdate:
public class TrackingTag
{
public int ID { get; set; }
}
public class TrackingTagStatusUpdate
{
public int ID { get; set; }
public int TrackingTagID { get; set; }
public TrackingTag TrackingTag { get; set; }
public int Epoch { get; set; } //32-bit
[MaxLength(32)]
public string APConnectedSSID { get; set; }
}
As there will be many TrackingTagStatusUpdates, I want to add a field "LatestStatusUpdate" to TrackingTag, for performance reasons.
public class TrackingTag
{
public int ID { get; set; }
public int? LatestStatusUpdateID { get; set; }
public TrackingTagStatusUpdate LatestStatusUpdate { get; set; }
}
LatestStatusUpdate is optional, as it may not be set if there are not yet any Status Updates for the Tag.
Entity Framework Core complains that "The child/dependent side could not be determined for the one-to-one relationship between 'TrackingTag.LatestStatusUpdate' and 'TrackingTagStatusUpdate.TrackingTag'.". I then add
modelBuilder.Entity<TrackingTag>().HasOne(x => x.LatestStatusUpdate).WithOne(x => x.TrackingTag).HasForeignKey<TrackingTagStatusUpdate>(x => x.TrackingTagID);
to OnModelCreating(ModelBuilder modelBuilder), however this results in Entity Framework Core creating a relationship with a Unique constraint, which will not work as there will be many TrackingTagStatusUpdate with the same TrackingTagID.
How do I do this correctly?
This seems to have worked:
public class TrackingTag
{
public int ID { get; set; }
[ForeignKey(nameof(LatestStatusUpdate))]
public int? LatestStatusUpdateID { get; set; }
public TrackingTagStatusUpdate LatestStatusUpdate { get; set; }
}
I'm not sure how to achieve the same with the Fluent API though.

Entity Framework Model Properties Not Created On Update-Database Command

I recently needed to change the type of three properties in a model class from string to an ICollection custom type as shown below.
There are also three classes (SpecialType, TypeToAdd, TypeToRemove) that were added that have a primary key ID, name (string), qty (int) and a FK to corresponding Subscriptions_Regular_Id.
I ran the migration, then update-database to script, but when I ran the script in SSMS console it left off the three ICollection properties below. It did create the three dependent tables with their foreign keys back to the parent, but I can't understand why it's not creating these three ICollection properties. Something simple I'm overlooking I'm sure and wanted to get some input if anyone might have a suggestion.
public class Subscriptions
{
[Key]
public int Subscriptions_Regular_Id { get; set; }
public string CustomerNumber { get; set; }
public string Type { get; set; }
public int TypeQty { get; set; }
public ICollection<SpecialType> SpecialType { get; set; }
public ICollection<TypeToAdd> TypeToAdd { get; set; }
public ICollection<TypeToRemove> TypeToRemove { get; set; }
}
For context:
Subscriptions can have many SpecialTypes, TypeToAdd, and TypeToRemove
SpecialTypes, TypeToAdd, TypeToRemove can be tied to only one Subscription.
Thanks in advance for any input.
====== EDIT ======
Adding 3 ICollection classes:
public class TypeToAdd
{
[Key]
public int TypeToAddId { get; set; }
public string TypeToAdd { get; set; }
public int Qty { get; set; }
public int Subscriptions_Regular_Id { get; set; }
public Subscriptions Subscriptions { get; set; }
}
The other two classes are the same as above other than the first two property names (they are TypeToRemove and SpecialType).
but I can't understand why it's not creating these three ICollection properties
Collection Navigation Properties are implemented using seperate tables with foreign keys. Relational databases don't have multi-valued attributes, so that's just how related collections are implemented in an RDBMS.
Try to change the classes to this
public class Subscription
{
[Key]
public int Id { get; set; }
public string CustomerNumber { get; set; }
public string Type { get; set; }
public int TypeQty { get; set; }
[InverseProperty(nameof(TypeToAdd.Subscription))]
public ICollection<TypeToAdd> TypeToAdds { get; set; }
[InverseProperty(nameof(SpecialType.Subscription))]
public virtual ICollection<SpecialType> SpecialTypes { get; set; }
[InverseProperty(nameof(TypeToRemove.Subscription))]
public ICollection<TypeToRemove> TypeToRemoves { get; set; }
}
public class TypeToAdd
{
[Key]
public int Id { get; set; }
public string TypeToAdd { get; set; }
public int Qty { get; set; }
public int SubscriptionId { get; set; }
[ForeignKey(nameof(SubscriptionId))]
[InverseProperty("TypeToAdds")]
public virtual Subscription Subscription { get; set; }
}
SpecialType and TypeToRemove classes should be configured the same way as TypeToAdd.

EF6: Using collection property without creating FK field in child table

I'm studying EF6 and think I know quite a bit already, but couldn't find a good solution (yet) for this:
Suppose I have the following model classes:
class LivingRoom {
public int Id { get; set; }
public string Name { get; set; }
public PersonTypeId { get; set; }
public IList<Person> Persons { get; set; }
}
class Person {
public int Id { get; set; }
public int PersonTypeId { get; set; }
public string Name { get; set; }
}
With these model classes I'm able to save and load via DbContext without any problem. Thanks to the navigation property in the "parent" LivingRoom class, the Persons collection will be included in this process. I don't have to load/save them separately.
UPDATE: Forgot the logical PersonTypeId field which will be used for determining which Persons should be in the collection property.
So far so good.
But EF6 is creating a FK in the Persons table, pointing to the LivingRooms table, which seems logical.
But what if I'm going to use the Persons table for a lot more other parent entities, like eg. "Bus" and "Plane", and therefore don't want to have a dependency (= FK field in LivingRooms table) in the Persons table?
Can I achieve this (don't create the FK field) without breaking the "include child list" load/save process as described?
If yes, how? And if no, why not?
NB: Please understand that I want to learn the best techniques. So good advice, to not doing this, is also welcome.
First , it's better to handle FK in Person Table ourself to do that web have this :
class LivingRoom
{
public int Id { get; set; }
public string Name { get; set; }
public IList<Person> Persons { get; set; }
}
class Person
{
public int Id { get; set; }
public string Name { get; set; }
public LivingRoom LivingRoom { get; set; }
public int LivingRoomId { get; set; }
}
now If you have others Entities Like Bus and ... so we have
public class Bus
{
public int Id { get; set; }
public ICollection<Person> People { get; set; }
}
and Updated Person class is :
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public LivingRoom LivingRoom { get; set; }
public int LivingRoomId { get; set; }
public Bus Bus{ get; set; }
public int BusId { get; set; }
}
you can set FK in Person Table as Nullable to do this :
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public LivingRoom LivingRoom { get; set; }
public int? LivingRoomId { get; set; }
public Bus Bus{ get; set; }
public int? BusId { get; set; }
}
As you can see We set BusId and LivingRoomId as nullable or you can just set one of them that you want
Note : You need to add some mapper to tell EF which field id FK and something like this ,...

Foreign keys with Code First in a Web API

Very simple question but it looks like I'm trying to implement a simple one-to-many relationship between two models.
So far, what I have is this :
A product class :
public class Products
{
public long Id { get; set; }
public long Code { get; set; }
public DateTime DateCreated { get; set; }
public DateTime DateModified { get; set; }
public Boolean Reviewed { get; set; }
[ForeignKey("BundleId")]
public int BundleId { get; set; }
public virtual Bundles Bundle { get; set; }
}
And the Defects class looks like this:
public class Defects
{
public long Id { get; set; }
public String Description { get; set; }
public String Picture { get; set; }
public DateTime DateCreated { get; set; }
[ForeignKey("ProductId")]
public int ProductId { get; set; }
public Products Product { get; set; }
[ForeignKey("UserId")]
public int UserId { get; set; }
public virtual Users User { get; set; }
}
I thought that I did not need to add an ICollection of Defects to the Products class because it's a "simple" one-to-many relationship and this code would be enought to be able to get the ID of a Product in the Defects class (I don't need more).
But, of course I get an exception :
The property 'ProductId' cannot be configured as a navigation property. The property must be a valid entity type and the property should have a non-abstract getter and setter
How may I solve that issue ?
I might be doing someting wrong with my two foreign keys but since I declared the name of the foreign keys, I assumed it would have been enought.
Thanks for your attention.
This is what your relationship can be distilled to.
Please note that ForeignKey annotation is applied to navigation property with the name of the key property.
If you build one-to-many relationship - then ICollection is absolutely necessary. Otherwise where's the "many"
public class Products
{
public int Id { get; set; }
public virtual List<Defects> Bundle { get; set; }
}
public class Defects
{
public long Id { get; set; }
public int ProductId { get; set; }
[ForeignKey("ProductId")]
public Products Product { get; set; }
}
FK can also be applied to the key property. But in that case you have to put the name of the instance of related class there
public class Defects
{
public long Id { get; set; }
[ForeignKey("Product")]
public int ProductId { get; set; }
public Products Product { get; set; }
}

How do I specify table for foreign key in entity framework?

All examples in tutorials I have read through only ever show 2 tables so I am confused on what to do in the following scenario.
Lets say we have 3 classes:
public class Product
{
public int id { get; set; }
public string name { get; set; }
public string skuA { get; set; }
public string skuB { get; set; }
public virtual SupplierA supplierA { get; set; }
public virtual SupplierB supplierB { get; set; }
}
public class Supplier A
{
public int id { get; set; }
public string name { get; set; }
public string sku { get; set; }
public int price { get; set; }
}
public class Supplier B
{
public int id { get; set; }
public string name { get; set; }
public string sku { get; set; }
public int price { get; set; }
}
If we need to join the appropriate product sku field then using the data annotation I have seen in tutorial it ends up looking like this:
[ForeignKey("sku")]
public string skuA { get; set; }
[ForeignKey("sku")]
public string skuB { get; set; }
How does entity framework know which foreign "sku" field we are annotating for? Does each foreign key have to be named differently? I imagine this would become awkward if we had a hundred suppliers.
Are there some additional parameters or markup to handle this? Any advice appreciated as I am finding this confusing.
I misunderstood the purpose of the foreign key attribute. It defines key on current class if it does not follow naming convention.
I was getting stuck as the error message I was getting stated I needed to use annotation or the fluent api but what it really meant was I had to use the fluent api as the relationship I wanted could not be specified with annotations.

Categories