Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# EF7实施TPH和x2B;M2M_C#_Entity Framework_Entity Framework Core - Fatal编程技术网

C# EF7实施TPH和x2B;M2M

C# EF7实施TPH和x2B;M2M,c#,entity-framework,entity-framework-core,C#,Entity Framework,Entity Framework Core,有没有更好的方法来实现这个最终目标,即在同一个表中存储相关的多对多实体的可轻松查询(并包含)的横截面 我一开始没有在联接表中实现TPH,但这使得在查询中使用一种或另一种类型更加复杂,afaict // table Related: [Id] public class Related { public Guid Id { get; set; } public List<RelatedOther> RelatedOthers { get; set; } = new Lis

有没有更好的方法来实现这个最终目标,即在同一个表中存储相关的多对多实体的可轻松查询(并包含)的横截面

我一开始没有在联接表中实现TPH,但这使得在查询中使用一种或另一种类型更加复杂,afaict

// table Related: [Id]
public class Related
{
    public Guid Id { get; set; }
    public List<RelatedOther> RelatedOthers { get; set; } = new List<RelatedOther>();
    public List<RelatedOtherOne> RelatedOtherOnes { get; set; } = new List<RelatedOtherOne>();
    public List<RelatedOtherTwo> RelatedOtherTwos { get; set; } = new List<RelatedOtherTwo>();
}

// table RelatedOther: [RelatedId, OtherId, Type]
public abstract class RelatedOther
{
    public Guid RelatedId { get; set; }
    public Guid OtherId { get; set; }

    public Related Related { get; set; }
    public Other Other { get; set; }
    public abstract RelatedOtherType Type { get; }
}
public class RelatedOtherOne : RelatedOther
{
    public override RelatedOtherType Type => RelatedOtherType.One;
    // should be unnecessary, 'Other' should be correct type
    public OtherOne OtherOne { get; set; }
}
public class RelatedOtherTwo : RelatedOther
{
    public override RelatedOtherType Type => RelatedOtherType.Two;
    // should be unnecessary, 'Other' should be correct type
    public OtherTwo OtherTwo { get; set; }
}
public enum  RelatedOtherType : int
{
    One = 1,
    Two = 2
}

// table Other: [Id, OneProp, TwoProp]
public abstract class Other
{
    public Guid Id { get; set; }
    public List<RelatedOther> RelatedOthers { get; set; } = new List<RelatedOther>();
}
public class OtherOne : Other
{
    public string OneProp { get; set; }
}
public class OtherTwo : Other
{
    public string TwoProp { get; set; }
}
//表相关:[Id]
公共类相关
{
公共Guid Id{get;set;}
public List RelatedOthers{get;set;}=new List();
public List relatedOtherOne{get;set;}=new List();
public List RelatedOtherTwos{get;set;}=new List();
}
//表RelatedOther:[RelatedId,OtherId,Type]
公共抽象类RelatedOther
{
公共Guid RelatedId{get;set;}
公共Guid OtherId{get;set;}
公共相关的{get;set;}
公共其他{get;set;}
公共抽象RelatedOtherType{get;}
}
公共类RelatedOtherOne:RelatedOther
{
公共覆盖RelatedOtherType=>RelatedOtherType.One;
//应为不必要,“其他”应为正确类型
公共OtherOne OtherOne{get;set;}
}
公共类RelatedOther二:RelatedOther
{
公共覆盖RelatedOtherType=>RelatedOtherType.Two;
//应为不必要,“其他”应为正确类型
public OtherTwo OtherTwo{get;set;}
}
公共枚举RelatedOtherType:int
{
1=1,
二=2
}
//表其他:[Id,OneProp,TwoProp]
公共抽象类其他
{
公共Guid Id{get;set;}
public List RelatedOthers{get;set;}=new List();
}
公共类其他一个:其他
{
公共字符串OneProp{get;set;}
}
公共类其他二:其他
{
公共字符串TwoProp{get;set;}
}
TPH已映射
M2M在HasKey()中映射+鉴别器


当“相关”实体演变为类似于“其他”的TPH战略时,这变得更加复杂(如果不是不可能?)

我没有简单的解决办法,但当我偶然发现同样的问题时,我想我将分享我迄今为止的成果

我发现我通常需要将所有或多种类型的关系加载到TPH结构的类中

因此,我使用基本的多对多类来加载相关对象。因此,此类不能是抽象的:

public class Event2Location
{
    [Required]
    public Event Event { get; set; }
    public int EventId { get; set; }

    [Required]
    public Location Location { get; set; }
    public int LocationId { get; set; }

    public byte EntityType { get; set; }
}
派生类仅添加一些属性以便于访问:

public class Event2Country : Event2Location
{
    [NotMapped]
    public Country Country
    {
        get { return base.Location as Country; }
        set { base.Location = value; }
    }

    [NotMapped]
    public int CountryId
    {
        get { return base.LocationId; }
        set { base.LocationId = value; }
    }
}
事件中
类别I有:

public virtual ICollection<Event2Location> Event2Locations { get; set; }

[NotMapped]
public virtual ICollection<Event2Country> Event2Countries => Event2Locations?.OfType<Event2Country>().ToList();
// I should probably add some caching here if accessed more often

[NotMapped]
public virtual ICollection<Event2City> Event2Cities => Event2Locations?.OfType<Event2City>().ToList();
我可以根据需要使用NotMapped集合访问特定类型的关系

我仍然使用派生的Event2。。。类以添加新关系

如您所见,我已将一列
EntityType
添加到我用作TPH鉴别器的多对多类中。通过此列,我还可以声明如果我不想加载所有类型的关系/实体,我希望加载哪些类型的关系/实体

modelBuilder.Entity<Event2Location>()
    .HasDiscriminator<byte>("EntityType")
    .HasValue<Event2Location>(0)
    .HasValue<Event2Country>(1)
modelBuilder.Entity()
.HasDiscriminator(“EntityType”)
.HasValue(0)
.HasValue(1)
这肯定远远不够完美,但我最终放弃了优化它。首先,EFCore必须变得更加成熟。其次,我想看看我是如何实际使用这些结构的


PS:实际上我的位置TPH结构中有父子关系。在这里,我没有为Relationship类创建TPH结构(正如您所说的——不可能或至少不合理)。我添加了ParentType和ChildType。因此,我可以确定实际要加载哪些关系。然后,从结果中手动获取客户端所需类型的相关位置

我没有简单的解决办法,但当我偶然发现同样的问题时,我想我将分享我迄今为止的成果

我发现我通常需要将所有或多种类型的关系加载到TPH结构的类中

因此,我使用基本的多对多类来加载相关对象。因此,此类不能是抽象的:

public class Event2Location
{
    [Required]
    public Event Event { get; set; }
    public int EventId { get; set; }

    [Required]
    public Location Location { get; set; }
    public int LocationId { get; set; }

    public byte EntityType { get; set; }
}
派生类仅添加一些属性以便于访问:

public class Event2Country : Event2Location
{
    [NotMapped]
    public Country Country
    {
        get { return base.Location as Country; }
        set { base.Location = value; }
    }

    [NotMapped]
    public int CountryId
    {
        get { return base.LocationId; }
        set { base.LocationId = value; }
    }
}
事件中
类别I有:

public virtual ICollection<Event2Location> Event2Locations { get; set; }

[NotMapped]
public virtual ICollection<Event2Country> Event2Countries => Event2Locations?.OfType<Event2Country>().ToList();
// I should probably add some caching here if accessed more often

[NotMapped]
public virtual ICollection<Event2City> Event2Cities => Event2Locations?.OfType<Event2City>().ToList();
我可以根据需要使用NotMapped集合访问特定类型的关系

我仍然使用派生的Event2。。。类以添加新关系

如您所见,我已将一列
EntityType
添加到我用作TPH鉴别器的多对多类中。通过此列,我还可以声明如果我不想加载所有类型的关系/实体,我希望加载哪些类型的关系/实体

modelBuilder.Entity<Event2Location>()
    .HasDiscriminator<byte>("EntityType")
    .HasValue<Event2Location>(0)
    .HasValue<Event2Country>(1)
modelBuilder.Entity()
.HasDiscriminator(“EntityType”)
.HasValue(0)
.HasValue(1)
这肯定远远不够完美,但我最终放弃了优化它。首先,EFCore必须变得更加成熟。其次,我想看看我是如何实际使用这些结构的


PS:实际上我的位置TPH结构中有父子关系。在这里,我没有为Relationship类创建TPH结构(正如您所说的——不可能或至少不合理)。我添加了ParentType和ChildType。因此,我可以确定实际要加载哪些关系。然后,从结果中手动获取客户端所需类型的相关位置

我决定,如果m2m关联的末端是TPH,那么联接表本身也应该反映该TPH,不管我是否为所有这些TPH类型在任何一端公开导航属性。在我看来,这只是一个更简洁的设计。这将允许框架处理您作为
[notmap]进行的导航属性转换
使用cast。当我在基类上使用
abstract
时,它不会阻止我仅对该基类进行查询-如果查询的结果集为多个派生类型,EF将实例化正确的派生类型,相应派生类型中的实例将自动填充该实例。如果您的模型有2个(并且只有2个)派生类型,那么基类应该是抽象的。没有EventType鉴别器值的Event2Location实例实际上没有意义,对吗?所以你永远都不应该相信