I am using EF 6 Code First, I don't understand why one column is not created for a property of my Model.
Here is the first class :
public class Original
{
public int ID { get; set; }
public string Nom { get; private set; }
public Historique Historique { get; private set; }
public Traduction Traduction { get; private set; }
}
And here is the second class :
public class Traduction
{
public int ID { get; set; }
public Utilisateur Traducteur { get; private set; }
public Original Original { get; private set; }
public string Content { get; private set; }
}
EF doesn't create the FK column for Traduction and Original. (The Traduction table doesn't contains a FK column for Original and vice versa) but it perfectly creates all the other column and FKs.
I am playing with Fluent API to set up the relationships. I have tried both to rely on the automatic conventions, and to explicitly configure the relation with :
modelBuilder.Entity<Original>().HasRequired(o => o.Traduction).WithRequiredPrincipal(t=>t.Original).WillCascadeOnDelete(true);
But the columns are still not created.
Thank you for your help
Update
I don't know if it is useful but I would like to add one information, my Dbset are defined like this in the context class :
public DbSet<Traduction> Traductions { get; set; }
public DbSet<Original> Originaux { get; set; }
"Originaux" if the French plural for "Originals". However I have noticed that the Table created by EF is Named "Originals", and doesn't follow the name of the DbSet. I don't know, perhaps it might be a cause of the problem.
As Dismissile said, EF doesn't create an extra column to hold the foreign keys because it is a one-to-one relationship. This is a normal behaviour and nothing is actually wrong.
Related
I'm working on a serverside blazor project (.net 6) using Entity Framework with code first. I have two tables, let's say (in order to protect private data), we have the Tables Band and Bandsman. Originally, every band could have exactly one bandsman, a bandsman could be connected to more then one band though. It's an example, so please don't question this assumptive circumstances.
I created two classes:
[Table("Band")]
public partial class Band
{
[Key]
public int Id { get; set; }
public string BandName { get; set; }
public int? BandsmanId { get; set; }
public virtual Bandsman Bandsman { get; set; }
}
[Table("Bandsman")]
public partial class Bandsman
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public virtual List<Band> Band { get; set; }
}
So far everything works fine. Entity Framework set the correct foreign key. But now I have to insert a second bandsman. Let's say, the first bandsman is a keyboarder, now I need a drummer as well. So I altered the existing classes:
[Table("Band")]
public partial class Band
{
[Key]
public int Id { get; set; }
public string BandName { get; set; }
public int? BandsmanId { get; set; }
public int? DrummerId { get; set; }
public virtual Bandsman Bandsman { get; set; }
public virtual Bandsman Drummer { get; set; }
}
[Table("Bandsman")]
public partial class Bandsman
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public virtual List<Band> Band { get; set; }
public virtual List<Band> Drummer { get; set; }
}
I know I have to tell Entity Framework now how to map the tables. So I added mapping instructions to the OnModelCreating-Method in DbContext:
builder.Entity<Band>().HasOne(a => a.Bandsman).WithMany().HasForeignKey(b => b.BandsmanId);
builder.Entity<Band>().HasOne(a => a.Drummer).WithMany().HasForeignKey(b => b.DrummerId);
This doesn't work. When I create the migrations I see that Entity Frameworks tries to create new Columns BandsmanId1 and BandsmanId2 to the Band-Table instead of using the Columns I defined.
So I tried to add the instructions the other way around, too, in addition to the previous ones:
builder.Entity<Bandsman>().HasMany<Band>(a => a.Band).WithOne().HasForeignKey(b => b.BandsmanId);
builder.Entity<Bandsman>().HasMany<Band>(a => a.Drummer).WithOne().HasForeignKey(b => b.DrummerId);
It's still the same, Entity Framework tries to add new columns and map the foreign keys to them.
I also tried to rename Band.BandsmanId to Band.KeyboarderId or rather add and map a new column with the new name (so existing data won't get lost), rename Band.Bandsman to Band.Keyboarder and Bandsman.Band to Bandsman.Keyboarder. With no effect, Entity Framework still seems incapable to use the colums I want it to use. I guess the instructions I added to OnModelCreating in DbContext are incorrect, but I'm not able to find out how to put it right. I found some examples here on stackoverflow and elsewhere, but I can't manage to convert one of this examples to my code.
So I hope someone can help me to put the classes and instructions right.
After posting my question, I found the solution in a post that was shown as possibly related:
Entity Framework Code First - two Foreign Keys from same table
I was close, my only mistake was not to name the virtual List-Property of the Bandsman-Class in the .HasMany()-Part of the instructions. So Entity Framework didn't now these properties were related to the foreign key columns in the band-table and tried to create the assumed-to-be-missing columns on its own. This way it works:
builder.Entity<Band>().HasOne(a => a.Bandsman).WithMany(b => b.Band).HasForeignKey(a => a.BandsmanId);
builder.Entity<Band>().HasOne(a => a.Drummer).WithMany(b => b.Drummer).HasForeignKey(a => a.DrummerId);
My database entity project has count about 30 columns, I would like to create clear EF Core model which many of them is grouped in several classes.
For example, overriding entity is Sensors and it has two elements (Int ID, ElectricalData electricalData), ElectricalData is a seperate class which has next 3 seperate classes and two bool and string objects.
A model constructed in this way in Add-Migration process returns feedback that sub-entities doesn't have a primary key, but they shouldn't contain PK, because only Sensors class should have a primary key.
How can I solve this problem? Does this idea is correct?
Code below:
public class SensorModel
{
[Key]
public int ID { get; set; }
public ElectricalDataModel ElectricalData { get; set; }
}
public class ElectricalDataModel
{
public TensionModel Tension { get; set; }
public CurrentModel Current { get; set; }
public string SecurityClass { get; set; }
public ResistanceModel Resistance { get; set; }
public bool ReversePolarizationSecurity { get; set; }
}
public class TensionModel
{
public double Minimum { get; set; }
public double Maximum { get; set; }
public string Current { get; set; }
}
//.......................................... and so on
What are you asking was called Complex Types, and the EF Core term is Owned Entity Types. By default they share the same table as the owner and are used to just logically separate (group) the related properties - exactly the goal you are describing.
The easiest way to identify a class as owned type in EF Core 2.1 is to mark it with OwnedAttribute:
[Owned]
public class ElectricalDataModel
{
// Properties..
}
[Owned]
public class TensionModel
{
// Properties..
}
//.......................................... and so on
Of course the same can be achieved via the OwnsOne fluent API, which also allows you to configure the column names and other attributes for the owned entity per owner.
I create a model in EF6 that contains several tables one of my tables is ContentGrouptable with this structure :
public partial class ContentGroup
{
public ContentGroup()
{
this.Contents = new HashSet<Content>();
this.ContentGroups = new HashSet<ContentGroup>();
}
public int Id { get; set; }
public string Name { get; set; }
public string Visible { get; set; }
public long Ordering { get; set; }
public string CommentState { get; set; }
public int ContentGroupId { get; set; }
public virtual ICollection<Content> Contents { get; set; }
public virtual ICollection<ContentGroup> ContentGroups { get; set; }
public virtual ContentGroup ContentGroup1 { get; set; }
}
As you can see this table has a relation whit itself .One to many on Id column.It this table we have a FK-ContentGroupId that refers to itself(ContentGroup).So i create a view for this entity using MVC4(ASP) so when i want to insert a value to my table i got this error:
"Unable to determine a valid ordering for dependent operations. Dependencies may
exist due to foreign key constraints, model requirements, or store-generated
values."
So what should i do ?it because of FK?
Best regards
The problem is that you have a non-nullable ContentGroupId. This means that when you insert a ContentGroup, you have to set its parent ContentGroup as well. But this a chicken and egg problem (or: no "valid ordering"). You can't insert a parent and child at the same time, it's always a sequential operation. And then, there must always be a "mother of all parents", not having a parent itself.
So, make ContentGroupId nullable and map the associations like so:
modelBuilder.Entity<ContentGroup>()
.HasOptional(cg => cg.ContentGroup1)
.WithMany(cg => cg.ContentGroups)
.HasForeignKey(cg => cg.ContentGroupId);
I have those two tables in my DataBase -
Material:
public class Material
{
[Required]
[MaxLength(10)]
public string Code { get; set; }
[MaxLength(40)]
public string Color { get; set; }
[MaxLength(40)]
public string Description { get; set; }
[MaxLength(255)]
public string Picture { get; set; }
public long MaterialTypeId { get; set; }
public virtual MaterialType MaterialType { get; set; }
}
and MaterialType :
public class MaterialType
{
[MaxLength(40)]
public string MatType { get; set; }
public virtual ICollection<Material> Materials { get; set; }
}
Then I call a method that populates all my tables with dummy data but the problem is that the Foreign Key could not be null and I still don't have data generated obviously. I tried to change the order the methods for creating the dummy data are called but this seems to not work. I wonder is there any easy way to work around this problem or maybe something that i don't know for managing this problem?
So in my case which is - the dummy data is created when the DB is created to work around the problem with Foreign Keys which could not be null the easiest way was to explicitly set the type of the property to nullable. As is in my code long?. This allows me to populate the table with data using null FK and then set the values I need.
Consider the following model classes:
public class Thing
{
public int Id { get; set; }
[Required]
public Text Subject { get; set; }
[Required]
public Text Body { get; set; }
}
public class Text
{
public int Id { get; set; }
public string Value { get; set; }
}
The model is simple - each Thing must reference to two Text entities. Each Text entry at any point in time should be referenced only by a single entity of any other type (Thing is not the only one).
Is it possible to configure EF5 to automatically delete all referenced Texts when Thing gets deleted (via context.Set<Thing>().Remove), or should it be done with a database trigger?
You just need to configure CASCADE DELETE at database level and don't have to do anything special at Entity framework level.