i have these classes:
public class Event
{
[Key]
public int ID { get; set; }
[Required]
public string Name { get; set; }
[Required]
public DateTime Begin { get; set; }
[Required]
public DateTime End { get; set; }
public string Description { get; set; }
public virtual ICollection<EventRegistration> Registrations { get; set; }
public virtual ICollection<EventComment> Comments { get; set; }
}
public class EventComment
{
[Key]
public int ID { get; set; }
[Required]
public int PersonID { get; set; }
[Required]
public int EventID { get; set; }
[Required]
public DateTime EntryDate { get; set; }
[Required]
public string Comment { get; set; }
public int? ParentCommentID { get; set; }
public virtual Event CommentEvent { get; set; }
public virtual Person CommentPerson { get; set; }
public virtual EventComment ParentComment { get; set; }
public virtual ICollection<EventComment> ChildComments { get; set; }
}
In the context i have the following:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<EventComment>()
.HasMany(s => s.ChildComments)
.WithOptional()
.HasForeignKey(s => s.ParentCommentID);
}
The EventComments and children get loaded correctly.
But every Event loads all EventComments with that EventID.
The Event class should only load EventComments with no ParentID.
How can i do that?
If I understand correctly, you're doing something like
var event = (from e in ctx.Event.Include(p=>p.EventComment) select e);
and you don't want all of the EventComments loaded, just specific ones.
Unfortunately EF does not provide a mechanism to filter the .Include.
You can however use projections as outlined here:
https://stackoverflow.com/a/5666403/141172
Related
I'm still studying Entity Framework and tried to create a model including the foreign keys.
But when I tried to migrate the code, I got this error
Introducing FOREIGN KEY constraint 'FK_dbo.QuestionResults_dbo.QuestionsTables_QuetionsTableId' on table 'QuestionResults' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints
These are my model classes:
public class MainDetails
{
[Key]
public int Id { get; set; }
public string Language { get; set; }
[Required]
public string CustomerName { get; set; }
[Required]
public string ContactNumber { get; set; }
public string EmailAddress { get; set; }
[DisplayName("Service Type")]
[ForeignKey("QuestionsTable")]
public int ServiceTypeId { get; set; }
public virtual QuestionsTable QuestionsTable { get; set; }
[Required]
public string VehicleNumber { get; set; }
[Required]
public string ServiceLocation { get; set; }
public string Suggestion { get; set; }
public bool Status { get; set; } = true;
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Created Date")]
public DateTime CreatedDate { get; set; } = DateTime.Now;
public virtual QuestionResults QuestionResults { get; set; }
public virtual IList<QuestionResults> QuestionResultsMainlist { get; set; }
public virtual IList<QuestionsTable> QuestionsTables { get; set; }
}
public class QuestionsTable
{
[Key]
public int Id { get; set; }
public string ServiceType { get; set; }
public string Question { get; set; }
public virtual IList<MainDetails> MainDetailsServiceType { get; set; }
public QuestionsTable()
{
MainDetailsServiceType = new List<MainDetails>();
}
}
public class QuestionResults
{
[Key]
public int Id { get; set; }
[DisplayName("MainDetail ID")]
[ForeignKey("MainDetails")]
public int MainDetailsId { get; set; }
public virtual MainDetails MainDetails { get; set; }
[DisplayName("MainDetail ID")]
[ForeignKey("QuestionsTable")]
public int QuetionsTableId { get; set; }
public virtual QuestionsTable QuestionsTable { get; set; }
[Required]
public string CustoAnswer { get; set; }
}
This is the table structure I wanted to create:
To resolve this you can use the EF Model Builder
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<QuestionsTable>()
.HasRequired(a => a.MainDetails)
.WithOptionalDependent()
.WillCascadeOnDelete(false); //This is the important row
}
You'll have to play around with the type of relationship you would like along with whether you specify explicitly the foreign key. If you haven't seen this model builder before have a read here: https://learn.microsoft.com/en-us/ef/core/modeling/
Upon breaking your scenario down I noticed some "oddities". I reduced the noise in the domain model to from your example to this
public class MainDetails
{
[Key]
public int Id { get; set; }
[ForeignKey("QuestionsTable")]
public int ServiceTypeId { get; set; }
public virtual QuestionsTable QuestionsTable { get; set; }
public virtual QuestionResults QuestionResults { get; set; }
public virtual IList<QuestionResults> QuestionResultsMainlist { get; set; }
public virtual IList<QuestionsTable> QuestionsTables { get; set; }
}
public class QuestionsTable
{
[Key]
public int Id { get; set; }
public string ServiceType { get; set; }
public string Question { get; set; }
public virtual IList<MainDetails> MainDetailsServiceType { get; set; }
}
public class QuestionResults
{
[Key]
public int Id { get; set; }
[ForeignKey("MainDetails")]
public int MainDetailsId { get; set; }
public virtual MainDetails MainDetails { get; set; }
[ForeignKey("QuestionsTable")]
public int QuetionsTableId { get; set; }
public virtual QuestionsTable QuestionsTable { get; set; }
}
I few things I noted.
MainDetails contains both One-To-Many (QuestionTable) and Many-To-Many (IList) relationships? I'm unsure on your intention
QuestionsResults contains singular relationships to both entities which aren't replicated in the QuestionTable class? that's fine if it's intentional
ServiceType is a string in QuestionsTable but you are expecting an int as the foreign key in MainDetails?
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.
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; }
}
i have a question about relations between entities created in Code-First:
I have Models:
public class ProjectGroup
{
[Key]
public int ProjectGroupID { get; set; }
public string ProjectGroupName { get; set; }
//FK
public virtual ICollection<File> Files { get; set; }
public virtual ICollection<List> Lists { get; set; }
}
public class File
{
[Key]
public int FileID { get; set; }
public int ProjectGroupID { get; set; }
[Required]
[Display(Name="Ścieżka pliku")]
public string FilePath { get; set; }
[Required]
[Display(Name="Data Zapisu")]
[DataType(DataType.DateTime)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd hh:mm:ss}", ApplyFormatInEditMode = true)]
public DateTime FileSaveDate { get; set; }//no NULL=>error
[Display(Name="Suma MD5")]
[StringLength(32)]
public string FileMD5Hash { get; set; }
public string IPHost { get; set; }
public int FileTemplateID { get; set; }
[ForeignKey("ProjectGroupID")]
public virtual ProjectGroup ProjectGroup { get; set; }
[ForeignKey("FileTemplateID")]
public virtual FileTemplate FileTemplate { get; set; }
public virtual ICollection<List> Lists { get; set; }//klucz obcy dla listy
}
public class List
{
[Key]
public int ListID { get; set; }
public int UserID { get; set; }
public int ProjectGroupID { get; set; }
public int FileID { get; set; }
public bool Modified { get; set; }
public bool Verified { get; set; }
public bool Alive { get; set; }
[ForeignKey("UserID")]
public virtual User User { get; set; } //referencja,przekazanie nazwy FK
[ForeignKey("ProjectGroupID")]
public virtual ProjectGroup ProjectGroup { get; set; }
[ForeignKey("FileID")]
public virtual File File { get; set; }
}
And Context:
public class AWZDContext : DbContext
{
public AWZDContext()
{
}
public DbSet<User> Users { get; set; }
public DbSet<File> Files { get; set; }
public DbSet<List> Lists { get; set; }
public DbSet<RemotePC> RemotePCs { get; set; }
public DbSet<UserType> UserTypes { get; set; }
public DbSet<ProjectGroup> ProjectGroups { get; set; }
public DbSet<FileTemplate> FileTemplates { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<File>()
.HasRequired(f=>f.ProjectGroup)
.WithMany(t=>t.Files)
.WillCascadeOnDelete(false);
modelBuilder.Entity<List>()
.HasRequired(c => c.ProjectGroup)
.WithMany(d=>d.Lists)
.WillCascadeOnDelete(false);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
when I created models, I got the following errors: problem with multi-cascade delete. I added modelbuilder in on model creating.
First I added no parameter in WithMany() and it doubled relations in database like this
This created many double relations between List and ProjectGroup (File, the same, read below).
when changed to WithMany(d=>d.Lists) relations looks ok, made only once like between File and ProjectGroup.
Does modelBuilder double the effect of [foreignKey] in model?
Can anyone explain how this works? Why did it double relation earlier, with no parameter in WithMany()
i am developing a database with 3 tables
Trip Model:
[Key]
public int TripId { get; set; }
[ForeignKey("Driver")]
public int DriverId { get; set; }
public virtual Driver Driver { get; set; }
public string StartingPoint { get; set; }
public string Destination { get; set; }
public DateTime TimeDepart { get; set; }
public int SeatAvailable { get; set; }
public virtual ICollection<Driver> Drivers { get; set; }
public virtual ICollection<Passenger> Passengers { get; set; }
Driver model:
[Key]
public int DriverId { get; set; }
public string DriverName { get; set; }
[ForeignKey("Trip"), Column(Order = 0)]
public int TripId { get; set; }
public virtual Trip Trip { get; set; }
And last passenger model:
[Key]
public int PassengerId { get; set; }
public string PassengerName { get; set; }
[ForeignKey("Trip"), Column(Order = 1)]
public int TripId { get; set; }
public virtual Trip Trip { get; set; }
With:
public class LiveGreenContext: DbContext
{
public DbSet<Trip> Trips { get; set; }
public DbSet<Driver> Drivers { get; set; }
public DbSet<Passenger> Passengers { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
}
And i get the following error:
Model compatibility cannot be checked because the EdmMetadata type was
not included in the model. Ensure that IncludeMetadataConvention has
been added to the DbModelBuilder conventions.
Any solutions on this issue? Thanks!
Try adding a call to the Database.SetInitializer method in the Application_Start event handler of your Global.asax:
Database.SetInitializer<ContextName>(null);
where ContextName is the name of your custom DbContext class.