WillCascadeOnDelete not working - c#

I have two tables
public class ServiceRendering
{
[DataMember]
public int Id { get; set; }
[DataMember]
public virtual IList<ServiceRenderingProduct> ServiceRenderingProducts { get; set; }
}
public class ServiceRenderingProduct
{
[ForeignKey("ServiceRendering")]
[DataMember]
public int ServiceRenderingId { get; set; }
[DataMember]
public virtual ServiceRendering ServiceRendering { get; set; }
[DataMember]
public int Id { get; set; }
}
And set relation between them
modelBuilder.Entity<ServiceRendering>().HasMany(x => x.ServiceRenderingProducts).WithRequired(x => x.ServiceRendering).HasForeignKey(x => x.ServiceRenderingId ).WillCascadeOnDelete(true);
But on deleting ServiceRenderingEntity, I don't get deleting of ServiceRenderingProduct entities. Should I set any constraints in database? Or is there another reason?

Related

The member with identity 'PmData.SafetyRequirement_Assets' does not exist in the metadata collection.\r\nParameter name: identity

I am trying to update an record in my system. Everything on the model saves great, except any of my many to many type relationships on the form. When I get to those in my model it gives me the error. "The member with identity 'PmData.SafetyRequirement_Assets' does not exist in the metadata collection.\r\nParameter name: identity". I've read over some of the other answers but I do not have any triggers on my database, and I've gone through several changes in my model based on other suggestions and it doesn't seem to change anything. The project is in vNext.
Here is my first model
public partial class Asset : DataModel
{
[Required]
[StringLength(64)]
public string Name { get; set; }
[StringLength(256)]
public string Description { get; set; }
[StringLength(1024)]
public string SystemFunction { get; set; }
[StringLength(2048)]
public string Remarks { get; set; }
public bool IsSystem { get; set; }
public bool IsGrouping { get; set; }
[StringLength(128)]
public string FieldTag { get; set; }
[ForeignKey("Parent")]
public int? ParentId { get; set; }
[ForeignKey("Building")]
public int? BuildingId { get; set; }
public bool IsOperable { get; set; }
public bool IsAvailable { get; set; }
public virtual Asset Parent { get; set; }
public virtual Building Building { get; set; }
public virtual ICollection<Asset> Children { get; set; }
public virtual ICollection<DrawingReference> DrawingReferences { get; set; }
public virtual ICollection<SpecReference> SpecReferences { get; set; }
public virtual ICollection<SafetyRequirement> SafetyRequirements { get; set; }
public virtual ICollection<SupportSystem> SupportSystems { get; set; }
}
The model for one the other table with a many to many.
public partial class SafetyRequirement : DataModel
{
[StringLength(256)]
[Required]
public string Name { get; set; }
[StringLength(2048)]
public string SafetyFunction { get; set; }
[StringLength(2048)]
public string FunctionalRequirements { get; set; }
[StringLength(2048)]
public string SystemBoundary { get; set; }
[StringLength(255)]
public string Reference { get; set; }
[ForeignKey("QualityLevel")]
public int QualityLevelId { get; set; }
public virtual QualityLevel QualityLevel { get; set; }
public virtual ICollection<Asset> Assets { get; set; }
}
The map for the joining table
modelBuilder.Entity<Asset>().HasMany(t => t.SafetyRequirements)
.WithMany(t => t.Assets)
.Map(m =>
{
m.MapRightKey("SafetyRequirementId");
m.MapLeftKey("AssetId");
m.ToTable("AssetSafetyRequirement");
});
Finally here's the area that it fails...
public virtual void SaveAsync(TEntity model)
{
Task.Run(() =>
{
using (
var dbContext =
(TContext)
Activator.CreateInstance(typeof (TContext),
ConfigOptions == null ? ConfigService.ConnectionString : ConfigOptions.ConnectionString))
{
var dbSet = dbContext.Set<TEntity>();
dbSet.Attach(model);
dbContext.Entry(model).State = EntityState.Modified;
dbContext.SaveChanges();
}
});
}
Any information or pointers would be greatly appreciated.
You're trying to use both Fluent API and Data Annotations to define the relationships between your tables. Remove one or the other.

Entity Framework Unable to determine principal end of relationship. Multiple added entities may have same primary key

I'm having some issues with EF.
Migrations go fine, but when I try to run update-database I get the error :
Unable to determine the principal end of the 'LeagueInsight.Models.Image_Passive' relationship. Multiple added entities may have the same primary key.
Here are my models and config:
Passive.cs
public class Passive
{
public long Id { get; set; }
public string Description { get; set; }
public string Name { get; set; }
public string SanitizedDescription { get; set; }
// Navigation
public virtual Image Image { get; set; }
public virtual Champion Champion { get; set; }
}
Image.cs
public class Image
{
public long Id { get; set; }
public string Full { get; set; }
public string Group { get; set; }
public int H { get; set; }
public string Sprite { get; set; }
public int W { get; set; }
public int X { get; set; }
public int Y { get; set; }
// Navigation
public virtual Champion Champion { get; set; }
public virtual ChampionSpell ChampionSpell { get; set; }
public virtual Passive Passive { get; set; }
}
DBContext Configuration Partial:
modelBuilder.Entity<Passive>()
.HasRequired(p => p.Champion)
.WithRequiredPrincipal(c => c.Passive);
modelBuilder.Entity<Info>()
.HasRequired(i => i.Champion)
.WithRequiredPrincipal(c => c.Info);
modelBuilder.Entity<Image>()
.HasOptional(i => i.Champion)
.WithRequired(c => c.Image);
modelBuilder.Entity<Image>()
.HasOptional(i => i.Passive)
.WithRequired(p => p.Image);
base.OnModelCreating(modelBuilder);
It is just supposed to be a 1-1 relationship between the two, an I can't figure out why there would be multiple entities with the same Id here.
Edit: I was asked for the champion class:
public class Champion
{
public int Id { get; set; }
public string Blurb { get; set; }
public string Key { get; set; }
public string Lore { get; set; }
public string Name { get; set; }
public string Partype { get; set; }
public string Title { get; set; }
// Navigation
[InverseProperty("Ally")]
public virtual ICollection<Tip> Allytips { get; set; }
[InverseProperty("Enemy")]
public virtual ICollection<Tip> Enemytips { get; set; }
public virtual Image Image { get; set; }
public virtual Info Info { get; set; }
public virtual Passive Passive { get; set; }
public virtual ICollection<Recommended> Recommended { get; set; }
public virtual ICollection<Skin> Skins { get; set; }
public virtual Stats Stats { get; set; }
public virtual ICollection<ChampionSpell> Spells { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
}

Creating a Key Table and Domain Models

All,
I need to add a domain class for a new key table that relates a table of club members ([dbo].NewClubProspect) to emails ([dbo].NewClubEmail) sent to them.
I am not sure how to set this up in the domain classes.
Question
Need to annotate the key table (NewClubProspectNewClubEmail) Since both properties are foreign keys, not sure if I need an actual primary key, too? How do I annotate this?
Here is a diagram of how the tables relate. The table on the bottom of the diagram (NewClubProspectNewClubEmail) is the new table that I need to create in the database and in code, in a domain class.
Here are my domain classes (chopped down for brevity)
public class NewClub
{
public NewClub()
{
NewClubProspects = new List<NewClubProspect>();
NewClubEmails = new List<NewClubEmail>();
}
public int Id { get; set; }
public string NewClubName { get; set; }
public string NewClubLocation { get; set; }
public string NewClubType { get; set; }
public string NewClubCity { get; set; }
public string NewClubState { get; set; }
public string NewClubCountry { get; set; }
public virtual List<NewClubProspect> NewClubProspects { get; set; }
public virtual List<NewClubEmail> NewClubEmails { get; set; }
}
public class NewClubProspect
{
[Key]
public int Id { get; set; }
//Foreign Key
public int NewClubId { get; set; }
public bool IsConverted { get; set; }
public string ProspectFirstName { get; set; }
public string ProspectLastName { get; set; }
public string ProspectEmail { get; set; }
public virtual NewClub NewClub { get; set; }
public virtual List<NewClubEmail> NewClubEmails { get; set; }
}
public class NewClubEmail
{
//Primary key
[Key]
public int Id { get; set; }
//Foreign Key
public int NewClubId { get; set; }
public string Subject { get; set; }
public virtual List<NewClubProspect> Recipients { get; set; }
public string Body { get; set; }
public DateTime CreateDate { get; set; }
public DateTime ModifiedDate { get; set; }
public DateTime? SentDate { get; set; }
public NewClub NewClub { get; set; }
public NewClubEmail()
{
Recipients = new Collection<NewClubProspect>();
}
}
//---------------------------------------------------------
// Not sure what to do here. They are both foreign keys
//---------------------------------------------------------
public class NewClubProspectNewClubEmail
{
public int NewClubEmail_Id {get; set;}
public int NewClubProspect_Id {get; set;
}
Just mark both as Key:
[Key]
public int NewClubEmail_Id {get; set;}
[Key]
public int NewClubProspect_Id {get; set;}

One to many in Entity Framework using fluent mapping

Im trying to do a one-to-many map by using fluent api.
This is my classes
public class Product : EntityBase
{
public Product()
{
this.ProductArticles = new List<ProductArticle>();
}
[Key]
public int ProductId { get; set; }
public string Description { get; set; }
public string ReportText1 { get; set; }
public string ReportText2 { get; set; }
public bool Standard { get; set; }
public int ProductGroupId { get; set; }
public decimal? Surcharge1 { get; set; }
public decimal? Surcharge2 { get; set; }
public decimal? Surcharge3 { get; set; }
public decimal? Surcharge4 { get; set; }
public decimal PriceIn { get; set; }
public decimal PriceOut { get; set; }
public decimal PriceArtisanIn { get; set; }
public decimal PriceArtisanOut { get; set; }
public decimal PriceTotalIn { get; set; }
public decimal PriceTotalOut { get; set; }
public decimal PriceTotalOutVat { get; set; }
public decimal PriceAdjustment { get; set; }
public bool Calculate { get; set; }
public string Notes { get; set; }
[ForeignKey("ProductGroupId")]
public virtual ProductGroup ProductGroup { get; set; }
public virtual ICollection<ProductArticle> ProductArticles { get; set; }
}
public class ProductArticle : EntityBase
{
[Key]
public int ProductArticleId { get; set; }
public int ProductId { get; set; }
public int ArticleId { get; set; }
public decimal Qty { get; set; }
public decimal PriceIn { get; set; }
public bool Primary { get; set; }
public virtual Product Product { get; set; }
public virtual Article Article { get; set; }
}
Now i want from single Product include all ProductArticles
This is my mapping
public class ProductMap : EntityTypeConfiguration<Product>
{
public ProductMap()
{
// Primary Key
this.HasKey(p => p.ProductId);
// Table & Column Mappings
this.ToTable("Product");
this.HasMany(p => p.ProductArticles)
.WithOptional()
.Map(p => p.MapKey("ProductId").ToTable("ProductArticle"));
}
But it doesnt work.. Please help :)
First - by convention EF treats property with name equal to Id or EntityTypeName + Id is a primary key. So, you don't need to configure that manually.
Second - if you don't want table names to be plural, just remove that convention from your context instead of providing table name for each entity mapping:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
base.OnModelCreating(modelBuilder);
}
And last - EF smart enough to define foreign keys which have names like RelatedEntityTypeName + Id. So, you don't need any fluent configurations here.

EF 4.1 Code first multiple one-to-many associations

Here is my model
public class Horse
{
public int HorseId { get; set; }
public string Name { get; set; }
public string Gender { get; set; }
public LegType LegType { get; set; }
public Character Character { get; set; }
public int Hearts { get; set; }
public bool Retired { get; set; }
// Parents
public Horse Sire { get; set; }
public Horse Dam { get; set; }
// Internals
public int Stamina { get; set; }
public int Speed { get; set; }
public int Sharp { get; set; }
// Special
public int Dirt { get; set; }
// Externals
public int Start { get; set; }
public int Corner { get; set; }
public int OutOfTheBox { get; set; }
public int Competing { get; set; }
public int Tenacious { get; set; }
public int Spurt { get; set; }
//Races
public virtual ICollection<Race> RaceResults { get; set; }
//Training
public virtual ICollection<Training> TrainingResults { get; set; }
}
public class Race
{
public int RaceId { get; set; }
public int Favorite { get; set; }
public LegType LegType { get; set; }
public int Players { get; set; }
public DateTime Split { get; set; }
public DateTime Final { get; set; }
public int Position { get; set; }
public virtual int TrackId { get; set; }
public virtual Track Track { get; set; }
public virtual int LinkedHorseId { get; set; }
public virtual Horse LinkedHorse { get;set; }
}
public class Training
{
public int TrainingId { get; set; }
public string Type { get; set; }
public string Result { get; set; }
public string Food { get; set; }
public int Start { get; set; }
public int Corner { get; set; }
public int Outofthebox { get; set; }
public int Competing { get; set; }
public int Tenacious { get; set; }
public int Spurt { get; set; }
public virtual int LinkedHorseId { get; set; }
public virtual Horse LinkedHorse { get; set; }
}
public class Track
{
public int TrackId { get; set; }
public string Name { get; set; }
public int Distance { get; set; }
public bool G1 { get; set; }
public int Prize { get; set; }
}
And here is my fluent API code.
public class HorseTracker : DbContext
{
public DbSet<Horse> Horses { get; set; }
public DbSet<LegType> LegTypes { get; set; }
public DbSet<Character> Characters { get; set; }
public DbSet<Training> TrainingResults { get; set; }
public DbSet<Track> Tracks { get; set; }
public DbSet<Race> Races { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Race>()
.HasRequired(r => r.LinkedHorse)
.WithMany(h => h.RaceResults)
.HasForeignKey(r => r.LinkedHorseId);
modelBuilder.Entity<Training>()
.HasRequired(t => t.LinkedHorse)
.WithMany(t => t.TrainingResults)
.HasForeignKey(t => t.LinkedHorseId);
modelBuilder.Entity<Race>()
.HasRequired(r => r.Track)
.WithMany()
.HasForeignKey(r => r.TrackId)
.WillCascadeOnDelete(false);
}
}
I keep getting this error:
Unable to determine the principal end of an association between the types 'DOCCL.Models.Horse' and 'DOCCL.Models.Horse'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.
Any clue what i'm doing wrong.
I've been playing around with no foreign keys. making one of the required lists optional.
they all result in different errors.
mostly saying that the relation needs to be a 1:1 relation.
And once it said that it had a non nullable field.
I made that nullable int? and then i got the first error again.
I think you need to setup self-referencing relationships manually (specifically, the Horse class properties Sire and Dam are causing an issue).
Try this (in the answer):
What is the syntax for self referencing foreign keys in EF Code First?
You could add two more int IDs representing the foreign keys (SireId, DamId).
If you add this to your model configuration it should work:
modelBuilder.Entity<Horse>()
.HasRequired(h => h.Dam) // or HasOptional
.WithMany();
modelBuilder.Entity<Horse>()
.HasRequired(h => h.Sire) // or HasOptional
.WithMany();
The problem is that the mapping conventions try to create a one-to-one relationship between Dam and Sire and therefore cannot determine what's the principal and what's the dependent because both are optional. Anyway I guess you don't want a one-to-one relationships but actually two one-to-many relationships (the many-side (the "children") not being exposed in the model).

Categories