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.
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 received this error:
Introducing FOREIGN KEY constraint
'FK_dbo.STCIProductInteractiveInfoes_dbo.User_ModifyUserID' on table
'STCIProductInteractiveInfoes' may cause cycles or multiple cascade
paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify
other FOREIGN KEY constraints.
So I looked it up online (on stackoverflow) and I see that it can be because the foreign key is required. I commented out the required property and I am still getting this error.
Here is my class:
namespace PTEManager.Domain
{
public class PTEInteractiveCourse
{
[Key]
public Guid PTEInteractiveCourseId { get; set; }
[ScaffoldColumn(false)]
[Required]
public DateTime ModifyDate { get; set; }
[ScaffoldColumn(false)]
[ForeignKey("ModifyUser")]
//[Required]
public int ModifyUserId { get; set; }
public virtual OpsUser ModifyUser { get; set; }
[Display(Name = "Package")]
[Required]
public int PackageId { get; set; }
[ScaffoldColumn(false)]
[Display(Name = "")]
[Required]
public int Status { get; set; }
[Display(Name = "STCI Course")]
[ForeignKey("STCICourseID")]
[Required]
public Guid STCIProductInteractiveInfoID { get; set; }
public virtual STCIProductInteractiveInfo STCICourseID { get; set; }
}
}
and here is the code that it is crashing on:
[HttpGet]
public ActionResult Index()
{
var model = db.PTEInteractiveCourses
.Where(p => p.Status == 1)
.ToList();
return View(model);
}
When a user deletes an Interactive Course, a user should not be deleted from the user table; just the interactive course should be deleted. Which this error is happening on a LINQ query to list the data so I do not even know what deleting it would have to do with it, we will not be adding a delete function anyway. Well there will be a delete but all it will do is hide the interactive course from the user but it will save the data to prevent data loss.
I have found this code:
protected override void OnModelCreating( DbModelBuilder modelBuilder )
{
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
}
which should theoretically work because I do not need any cascading deletes for this project but where would I put this code? It says in my datacontext class but when I do I have a build error on the void keyword. Here is my datacontext class:
namespace PTEManager.Domain.Data
{
public class DataContext : DbContext, IDataContext
{
public DataContext()
: base("HelpDesk")
{
}
//public DataContext(DbConnection existingConnection, bool contextOwnsConnection)
// : base(existingConnection, contextOwnsConnection)
//{
//}
/// <summary>
/// any entity to be persisted must be declared here.
/// </summary>
///
public DbSet<OpsUser> OpsUsers { get; set; }
public DbSet<PTEInteractiveCourse> PTEInteractiveCourses { get; set; }
public DbSet<PTETrackingClass> PTETrackingClasses { get; set; }
public DbSet<STCIProductInteractiveInfo> STCIProductInteractiveInfos { get; set; }
}
}
OpsUser Class:
namespace PTEManager.Domain
{
[Table("User")]
public class OpsUser
{
[Key]
public int u_user_id { get; set; }
public Guid DepartmentID { get; set; }
[MaxLength(50)]
[Required]
public string email_addr { get; set; }
[MaxLength(30)]
[Required]
public string first_nme { get; set; }
[MaxLength(30)]
[Required]
public string last_nme { get; set; }
[Required]
public Guid msrepl_tran_version { get; set; }
[MaxLength(1)]
[Required]
public string status { get; set; }
[MaxLength(15)]
[Required]
public string user_nme { get; set; }
[Required]
public int u_branch_id { get; set; }
}
}
PTETrackingClass:
namespace PTEManager.Domain
{
public class PTETrackingClass
{
[Key]
public Guid PTETrackingClassId { get; set; }
[ScaffoldColumn(false)]
[Required]
public DateTime ModifyDate { get; set; }
[ScaffoldColumn(false)]
[ForeignKey("ModifyUser")]
[Required]
public int ModifyUserId { get; set; }
public virtual OpsUser ModifyUser { get; set; }
[Display(Name = "Extensions Allowed")]
[Required]
public int NumberOfExtensions { get; set; }
[ScaffoldColumn(false)]
[Required]
public int Status { get; set; }
[Display(Name="Tracking Class Code")]
[Required]
public Guid TrackingClassCode { get; set; }
}
}
STCIProductInteractiveInfo:
namespace PTEManager.Domain
{
public class STCIProductInteractiveInfo
{
[Key]
public Guid STCIProductInteractiveInfoID { get; set; }
public Guid MarketingTextID { get; set; }
[Required]
public DateTime ModifyDate { get; set; }
[ForeignKey("ModifyUser")]
//[Required]
public int ModifyUserID { get; set; }
public virtual OpsUser ModifyUser { get; set; }
[MaxLength(50)]
[Required]
public string STCICourseID { get; set; }
[MaxLength(100)]
[Required]
public string STCICourseName { get; set; }
public byte STCIProductEmailHTML { get; set; }
[MaxLength(255)]
public string STCIProductEmailHTMLDateType { get; set; }
public int STCIProductEmailHTMLFileLength { get; set; }
public byte STCIProductEmailText { get; set; }
[MaxLength(255)]
public string STCIProductEmailTextDataType { get; set; }
public string STCIProductEmailTextFileLength { get; set; }
[MaxLength(50)]
[Required]
public string STCITrackingClassCode { get; set; }
[MaxLength(100)]
[Required]
public string STCITrackingClassName { get; set; }
[Required]
public int u_product_id { get; set; }
}
}
You have a circular relation on your Tables to resolve you have to option:
1) If User is optional in STCIProductInteractiveInfo or PTEInteractiveCourse you could simply change
public class STCIProductInteractiveInfo // or PTEInteractiveCourse
{
[Required]
public int ModifyUserID { get; set; }
}
to
public class STCIProductInteractiveInfo // or PTEInteractiveCourse
{
// [Required] remove required attribute too
public int? ModifyUserID { get; set; }
}
2) But if you want keep User Required simply add this on your DbContext
public class DataContext : DbContext, IDataContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<STCIProductInteractiveInfo>()
.HasRequired(e => e.ModifyUser)
.WithMany()
.WillCascadeOnDelete(false);
}
}
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'm developing a C# .NET Framework 4.0 with Entity Framework 6.1.0.
I have an existing database and I have generated Code First classes with it.
These are my classes:
[Table("CODES")]
public partial class CODE
{
public CODE()
{
}
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long ID_CODE { get; set; }
[Key]
[Column(Order = 0)]
public byte CODE_LEVEL { get; set; }
[Key]
[Column("CODE", Order = 1)]
[StringLength(20)]
public string CODE1 { get; set; }
public byte? COMMISIONING_FLAG { get; set; }
public bool? IS_TRANSMITTED { get; set; }
public DateTime? TIMESPAN { get; set; }
[StringLength(50)]
public string USERNAME { get; set; }
[StringLength(50)]
public string SOURCE { get; set; }
public virtual AGGREGATION_CHILDS AGGREGATION_CHILDS { get; set; }
public virtual AGGREGATION AGGREGATIONS { get; set; }
}
public partial class AGGREGATION_CHILDS
{
[Key]
[Column(Order = 0)]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public long ID_AGGREGATION { get; set; }
[Key]
[Column(Order = 1)]
[StringLength(20)]
public string ID_CHILD { get; set; }
[Key]
[Column(Order = 2)]
public byte CODE_LEVEL { get; set; }
public int POSITION { get; set; }
public virtual AGGREGATION AGGREGATION { get; set; }
public virtual CODE CODE { get; set; }
}
[Table("AGGREGATIONS")]
public partial class AGGREGATION
{
public AGGREGATION()
{
AGGREGATION_CHILDS = new HashSet<AGGREGATION_CHILDS>();
}
[Key]
public long ID_AGGREGATION { get; set; }
[StringLength(20)]
public string ID_PARENT { get; set; }
public byte? PARENT_LEVEL { get; set; }
public virtual ICollection<AGGREGATION_CHILDS> AGGREGATION_CHILDS { get; set; }
public virtual CODE CODE { get; set; }
}
And model:
public partial class MyDbContext : DbContext
{
public MyDbContext()
: base("name=MyDbContext")
{
}
public virtual DbSet<AGGREGATION_CHILDS> AGGREGATION_CHILDS { get; set; }
public virtual DbSet<AGGREGATION> AGGREGATIONS { get; set; }
public virtual DbSet<CODE> CODES { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<AGGREGATION>()
.HasMany(e => e.AGGREGATION_CHILDS)
.WithRequired(e => e.AGGREGATION)
.WillCascadeOnDelete(false);
}
}
CODES primary key is (CODE_LEVEL, CODE1).
I have a one-to-one relationship between CODES and AGGREGATION_CHILDS.
CODES.CODE1 -> AGGREGATION_CHILDS.ID_CHILD
CODES.CODE_LEVEL -> AGGREGATION_CHILDS.CODE_LEVEL
And another one-to-one relationship between CODES and AGGREGATION.
CODES.CODE1 -> AGGREGATION.ID_PARENT
CODES.CODE_LEVEL -> AGGREGATION.PARENT_LEVEL
But in AGGREGATION foreign key is optional: ID_PARENT and PARENT_LEVEL could be NULL.
How can I set up those both relationships on OnModelCreating?
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