C# EF Core 3.0:实体中的多个导航属性

C# EF Core 3.0:实体中的多个导航属性,c#,entity-framework-core,ef-core-3.0,C#,Entity Framework Core,Ef Core 3.0,下面是我定义的两个实体,我使用的是EF Core 3.0。 每当我尝试创建一个新的迁移时,我总是会收到一个错误,说在多个关系中不能有相同的导航属性 我是EF Core的noob,解决这个问题的任何指针都会非常有用 public class Event { public Guid Id { get; set; } public EventContext StartContext { get; set; } public Ev

下面是我定义的两个实体,我使用的是EF Core 3.0。 每当我尝试创建一个新的迁移时,我总是会收到一个错误,说在多个关系中不能有相同的导航属性

我是EF Core的noob,解决这个问题的任何指针都会非常有用

public class Event
    {
        public Guid Id { get; set; }
        public EventContext StartContext { get; set; }
        
        public EventContext EndContext { get; set; } 
        public Guid CreatedBy { get; set; }
        public Guid UpdatedBy { get; set; }
        
    }

    public class EventContext
    {
        public Guid Id { get; set; }
        public Guid EventId { get; set; } //fk
        public Event Event { get; set; }
        public DateTime ApplicableDate { get; set; }        
    }

EF核心工具将告诉您:

Cannot create a relationship between 'Event.EndContext' and 'EventContext.Event', because there already is a relationship between 'Event.StartContext' and 'EventContext.Event'. Navigation properties can only participate in a single relationship.
此问题有两种简单的解决方案:

EventContext
类型上使用两个导航属性 如果您确实需要
EventContext
上的导航属性,而不仅仅是
Event
上的导航属性,那么以下功能将起作用:

公共类事件
{
公共Guid Id{get;set;}
通过{get;set;}创建的公共Guid
公共Guid由{get;set;}更新
public EventContext StartContext{get;set;}
public EventContext EndContext{get;set;}
}
公共类事件上下文
{
公共Guid Id{get;set;}
公共Guid事件ID{get;set;}
public DateTime applicatabledate{get;set;}
//“事件”上每个对应的导航属性都有一个导航属性。
公共事件StartContext{get;set;}
公共事件EndContextEvent{get;set;}
}
公共类上下文:DbContext
{
公共数据库集事件{get;set;}
公共数据库集事件上下文{get;set;}
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
modelBuilder.Entity(
实体=>
{
entity.HasOne(e=>e.StartContext)
.WithOne(e=>e.StartContextEvent)
.HasForeignKey(e=>e.EventId);
entity.HasOne(e=>e.EndContext)
.WithOne(e=>e.EndContextEvent)
.HasForeignKey(e=>e.EventId);
});
}
}
使用单向导航属性 如果您可以不使用
EventContext
上的导航属性,并且很乐意只使用
Event
上的导航属性,那么只需将其从
EventContext
中删除即可,以下操作也适用于您:

公共类事件
{
公共Guid Id{get;set;}
通过{get;set;}创建的公共Guid
公共Guid由{get;set;}更新
public EventContext StartContext{get;set;}
public EventContext EndContext{get;set;}
}
公共类事件上下文
{
公共Guid Id{get;set;}
公共Guid事件ID{get;set;}
public DateTime applicatabledate{get;set;}
}
公共类上下文:DbContext
{
公共数据库集事件{get;set;}
公共数据库集事件上下文{get;set;}
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
modelBuilder.Entity(
实体=>
{
entity.HasOne(e=>e.StartContext)
.WithOne()
.HasForeignKey(e=>e.EventId);
entity.HasOne(e=>e.EndContext)
.WithOne()
.HasForeignKey(e=>e.EventId);
});
}
}

请在问题中加入模型创建/迁移代码。同时添加您收到的完整错误消息。哦,好吧,似乎您有一个循环引用。。。事件引用了EventContext,EventContext也引用了EventContext,它保存了对事件的引用更改梯形图以仅引用事件id,应该执行您启动xjpn的技巧。根据您的建议,我删除了事件上下文中的导航属性“Event”。我正在考虑下面的替代方案,请让我知道您对它的看法
public class Event{…other props public ICollection EventContexts{get;set;}}public enum eventcotextype{Start=0,End=1}公共类EventContext{public Guid Id{get;set;}public Guid EventId{get;set;}public EventContextType EventContextType{get;set;}public DateTime applicatabledate{get;set;}
当然,如果这对您有效,您也可以走这条路线。但是如果一个
Event
每个
EventContextType
只能有一个
EventContext
(我假设是这样),那么您就需要删除
EventContext.Id
属性,并将其主键定义为
.HasKey(e=>new{e.EventId,e.EventContextType})
,以强制执行此行为,哪种方法的性能更好?性能上应该没有真正的差异。这可能更多的是一个在代码中什么更容易使用的问题。如果您希望将来会有比现在使用的2种类型多得多的
EventContext
类型,那么您的方法可能会更好。如果您希望现在只使用2,那么我将继续使用
StartContext
EndContext
属性,因为您的查询将更易于阅读和维护。