I am using EF Core in my Blazor Server project. I have an entity called Lesson. A Lesson can have one or more prerequisite Lessons that must be completed before it is accessible.
I would prefer to use data annotations to accomplish setting up this relationship if possible.
Is the (redacted) approach below correct?
public class Lesson : EntityBase
{
public List<LessonPrerequisiteLesson> PrerequisiteLessons { get; set; }
}
public class LessonPrerequisiteLesson : EntityBase
{
public int LessonID { get; set; }
public int PrerequisiteLessonID { get; set; }
[ForeignKey("PrerequisiteLessonID")]
[InverseProperty("PrerequisiteLessons")]
public Lesson PrerequisiteLesson { get; set; }
}
Related
I know my question is kinda broad but I haven't found any good answers online.
I am building an ASP.NET Core MVC web app. I am looking for tips on how to bind a specific user to entities (classes in model). The problem is really about how to bind a certain user to a certain entity in the database.
Any help would be greatly appreciated.
ApplicationUser (or IdentityUser) is like any other entity class.
Creating a 1-n relationship, for example, would look something like:
public class ApplicationUser : IdentityUser
{
public virtual IList<MyEntity> MyEntities { get; set; } // navigation property
}
public class MyEntity
{
public int Id { get; set; }
public string CreatedByUserId { get; set; } // FK
public ApplicationUser CreatedByUser { get; set; } // Navigation property
}
You could also do this the fluent way:
public class ApplicationUser : IdentityUser { }
public class MyEntity
{
public int Id { get; set; }
public string CreatedByUserId { get; set; }
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<MyEntity>(b => {
b.HasOne<ApplicationUser>()
.WithMany()
.HasForeignKey(myEntity => myEntity.CreatedByUser);
});
}
}
I am trying this activity to clone from existing .edmx project to code first.
I have two entities. I want to have many to many relation without creating a new table. I am using EF Core 2.0 code first approach.
Please find below the entity i have created. I am not sure whether is this is the right way to do this.
I would like to have the foreign key column on both the tables ie. WorkflowId and WorkCaseId on WorkCase and Workflow tables respectively.
public class WorkCase
{
[Key]
public int WorkCaseId { get; set; }
public int WorkflowId { get; set; }
public int CaseDetailId {get;set;}
public CaseDetail CaseDetail {get;set;}
public WorkFlow WorkFlow { get; set; }
public ICollection<WorkFlow> WorkFlows { get; set; }
}
public class WorkFlow : BaseEntity
{
[Key]
public int WorkFlowId { get; set; }
public string Comment { get; set; }
public DateTime? UpdateDate { get; set; }
public int WorkCaseId { get; set; }
public WorkCase WorkCase { get; set; }
public ICollection<WorkCase> WorkCases { get; set; }
}
My expectation is as below. Can anyone help how to achieve the EF Core configuration:
- Workcase will have the latest workflowid
- workflow will have history for each workcaseid.
Thanks
UPDATE: EF5+ supports many-to-many without explicitly mapping the join table. See this EF announcement
As commented on your question, EF Core <= 2.2 does not yet support many-to-many relationships without a join table. This is an issue tracked in the EF Core repo's backlock, and will maybe make it into version 3.0.
In your case you'll need to introduce a new table that relates to both parent tables. In this case, your model will like something like the following:
public class WorkCase
{
public int WorkCaseId { get; set; }
public int CaseDetailId { get; set; }
public CaseDetail CaseDetail { get; set; }
public ICollection<WorkCaseWorkflow> Workflows { get; set; }
}
public class Workflow
{
public int WorkflowId { get; set; }
public string Comment { get; set; }
public DateTime? UpdateDate { get; set; }
public ICollection<WorkCaseWorkflow> WorkCases { get; set; }
}
public class WorkCaseWorkflow
{
public int WorkCaseId { get; set; }
public WorkCase WorkCase { get; set; }
public int WorkflowId { get; set; }
public Workflow Workflow { get; set; }
}
Then in your DbContext subclass, override the OnModelCreating and add the following code:
protected override void OnModelCreating(ModelBuilder builder)
{
var ww = builder.Entity<WorkCaseWorkflow>();
ww.HasKey(w => new { w.WorkCaseId, WorkflowId });
ww.HasOne(w => w.WorkCase)
.WithMany(wc => wc.Workflows)
.HasForeignKey(w => w.WorkCaseId);
ww.HasOne(w => w.Workflow)
.WithMany(wc => wc.WorkCases)
.HasForeignKey(w => w.WorkflowId);
}
I'm not familiar with your model, but you can move the shared properties to the join table.
However, there is a great series of articles by #Arthur Vickers (a member in the EF Core dev team) on how to easen up many-to-many relationships:
Part 1: The basics
Part 2: Hiding as IEnumerable
Part 3: Hiding as ICollection
Part 4: A more general abstraction
I am trying to create a many-to-many relationship between ApplicationUser and Reserve.
public class ApplicationUser : IdentityUser
{
public ApplicationUser()
{
this.Reserves = new HashSet<Reserve>();
}
public bool IsProfessional { get; set; }
public virtual ICollection<Reserve> Reserves { get; set; }
}
public class Reserve
{
public Reserve()
{
this.Usuarios = new HashSet<ApplicationUser>();
}
public int ID { get; set; }
public string Begin { get; set; }
public string End { get; set; }
public string Date { get; set; }
public string Status { get; set; } //free , reserved, confirmed, canceled
public DateTime LastUpdate { get; set; }
public virtual ICollection<ApplicationUser> Usuarios { get; set; }
}
But I cant add the migration
PM> Add-Migration user-reserve-relationship
Unable to determine the relationship represented by navigation property 'ApplicationUser.Reserves' of type 'ICollection<Reserve>'. Either manually configure the relationship, or ignore this property from the model.
Anyway, the same relationship works well to others entities but not ApplicationUser.
Can I use ApplicationUser many-to-many?
I found the follow in ef core :
Many-to-many relationships without an entity class to represent the join table are not yet supported.
So my question is closed.
I have two to be related entities as below :
public class VehicleExtraEntity
{
public int Id { get; set; }
public Guid NameKey { get; set; }
public virtual ICollection<WordEntity> WordsOfName { get; set; }
}
And the other entity :
public class WordEntity
{
public int Id { get; set; }
public string Content { get; set; }
public Guid Key { get; set; }
}
My purpose is write multi language supported db tables. For example ;
WordEntity1 : {Id=1, Content="Child Seat", Key="abcdef-12456"}
WordEntity2 : {Id=2, Content="Çocuk Koltuğu", Key="abcdef-12456"} --> Same Key
VehicleExtraEntity1 : {Id=1, NameKey = "abcdef-123456"}
I have tried fluent api but that support only relationships with navigation property. And it wants to me use many to many relationship. But I want resolve my problem as I wrote as above.
I'm producing a simple composite patterned entity model using EF4 w/ the code-first CTP feature:
public abstract partial class CacheEntity
{
[Key]public string Hash { get; set; }
public string Creator { get; set; }
public int EntityType { get; set; }
public string Name { get; set; }
public string Predecessor { get; set; }
public DateTime DateTimeCreated { get; set; }
public virtual ICollection<CacheReference> References { get; set; }
}
public partial class CacheBlob : CacheEntity
{
public byte[] Content { get; set; }
}
public partial class CacheCollection : CacheEntity
{
public virtual ICollection<CacheEntity> Children { get; set; }
}
public class CacheReference
{
public string Hash { get; set; }
[Key]public string Reference { get; set; }
public virtual CacheEntity Entity { get; set; }
}
public class CacheEntities : DbContext
{
public DbSet<CacheEntity> Entities { get; set; }
public DbSet<CacheReference> References { get; set; }
}
Before I split out the primitive/collection derived classes it all worked nicely, but now I get this:
Unable to determine the principal end of the 'Cache.DataAccess.CacheEntity_References'
relationship. Multiple added entities may have the same primary key.
I figured that it may have been getting confused, so I thought I'd spell it out explicitly using the fluent interface, rather than the DataAnnotation attributes. Here's what I think defines the relationship properly:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<CacheEntity>().HasKey(ce => ce.Hash);
modelBuilder.Entity<CacheEntity>().HasOptional(ce => ce.References).WithMany();
modelBuilder.Entity<CacheReference>().HasKey(ce => ce.Reference);
modelBuilder.Entity<CacheReference>().HasRequired(cr => cr.Entity).WithOptional();
}
But I must be wrong, because now I get this:
Entities in 'CacheEntities.CacheReferenceSet' participate in the
'CacheReference_Entity' relationship. 0 related 'Entity' were found. 1 'Entity' is expected.
Various other ways of using the fluent API yield different errors, but nothing succeeds, so I am beginning to wonder whether these need to be done differently when I am using inheritance.
Any clues, links, ideas, guidance would be very welcome.
using the MapHierarchy works for me:
protected override void OnModelCreating(ModelBuilder builder){
builder.Entity<CacheBlob>().HasKey(b=> b.Hash).MapHierarchy();
}
As an example.
Further reference : http://blogs.msdn.com/b/efdesign/archive/2009/10/12/code-only-further-enhancements.aspx