Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/310.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# 在实体框架中存储基于接口的关系_C#_Entity Framework - Fatal编程技术网

C# 在实体框架中存储基于接口的关系

C# 在实体框架中存储基于接口的关系,c#,entity-framework,C#,Entity Framework,我有这个领域的设计理念,我想实施。我正在使用实体框架作为存储机制,我能看到的唯一方法似乎并不理想 我有很多域对象,其中许多需要“可标记”。用户需要能够以某种方式“标记”每个人需要注意 所以我想我会创建这个界面: public interface IFlaggable { [Required] Tally Tally { get; } Guid? TallyId { get; } } 这些课程: public class Flag { public Guid Id

我有这个领域的设计理念,我想实施。我正在使用实体框架作为存储机制,我能看到的唯一方法似乎并不理想

我有很多域对象,其中许多需要“可标记”。用户需要能够以某种方式“标记”每个人需要注意

所以我想我会创建这个界面:

public interface IFlaggable
{
    [Required]
    Tally Tally { get; }
    Guid? TallyId { get; }
}
这些课程:

public class Flag
{
    public Guid Id { get; internal set; }
    [Required]
    public Tally Tally { get; internal set; }
    public Guid TallyId { get; internal set; }
    [Required]
    public User Creator { get; internal set; }
    public Guid CreatorId { get; internal set; }
    [Required]
    public FlagIndication Indication { get; internal set; }
}

public class Tally
{
    public Guid Id { get; internal set; }
    public IFlaggable Subject { get; internal set; }
    public ICollection<Flag> Flags { get; internal set; }
}
看起来很棒。就DB而言,它应该工作得很好,因为它是一对一的关系,而其他表总是包含一个指向计数表id字段的外键

问题在于实体框架查看了接口并阻塞了它。明显地我们知道实体框架不能很好地处理接口

我能看到的使其与实体框架一起工作的唯一方法是取消接口,创建从Tally继承的子类,如“TestFlaggablely”,然后每个其他对象都可以拥有自己的特殊snowflake Tally类

public class Tally
{
    public Guid Id { get; internal set; }
    public ICollection<Flag> Flags { get; internal set; }
}

[Table("TestFlaggableTallies")]
public class TestFlaggableTally : Tally
{
    public TestFlaggable Subject { get; internal set; }
}

public class TestFlaggable
{
    public Guid Id { get; internal set; }
    public TestFlaggableTally Tally { get; internal set; }
    public Guid? TallyId { get; internal set; }
}
公共类计数
{
公共Guid Id{get;内部集合;}
公共ICollection标志{get;internal set;}
}
[表(“TestFlaggableTables”)]
公共类TestFlaggablely:Tally
{
公共TestFlaggable主题{get;internal set;}
}
公共类TestFlaggable
{
公共Guid Id{get;内部集合;}
公共TestFlaggableTally{get;internal set;}
公共Guid?TallyId{get;内部集合;}
}
这应该行得通,但它看起来既愚蠢又臃肿

所以,我是来问你的。有更好的办法吗

我有一些基本的误解吗

这是我最好的选择吗


好的,点击我吧

我认为EF对接口没有这样的支持不正确,请参阅更新

我建议将接口重写为抽象类:

public abstract class FlaggableBase<T>
{
    public abstract T Id { get; internal set; }
    public abstract Tally Tally { get; internal set; }
    public abstract Guid? TallyId { get; internal set; }
}
公共抽象类FlaggableBase
{
公共抽象T Id{get;内部集合;}
公共抽象计数{get;内部集合;}
公共抽象Guid?TallyId{get;内部集合;}
}
请注意,我在基类中添加了Id属性,以确保从FlaggableBase派生的任何实体都有一个键(EF要求它能够区分实体)

然后像这样使用它:

public class TestFlaggable : FlaggableBase<Guid>
{
    public override Guid Id { get; internal set; }
    public override Tally Tally { get; internal set; }
    public override Guid? TallyId { get; internal set; }
}

public class Tally
{
    public Guid Id { get; internal set; }
    public FlaggableBase<Guid> Subject { get; internal set; }
    public ICollection<Flag> Flags { get; internal set; }
}

public class Flag
{
    public Guid Id { get; internal set; }
    [Required]
    public Tally Tally { get; internal set; }
    public Guid TallyId { get; internal set; }
    public Guid CreatorId { get; internal set; }
}
公共类TestFlaggable:FlaggableBase
{
公共重写Guid Id{get;internal set;}
公共覆盖计数{get;内部集;}
公共覆盖Guid?TallyId{get;内部集合;}
}
公务舱理货
{
公共Guid Id{get;内部集合;}
公共FlaggableBase主题{get;internal set;}
公共ICollection标志{get;internal set;}
}
公共班级旗帜
{
公共Guid Id{get;内部集合;}
[必需]
公共计数{get;内部集合;}
公共Guid TallyId{get;内部集合;}
公共Guid创建者ID{get;内部集合;}
}
使用抽象类而不是我马上看到的接口的唯一缺点是,您将无法利用延迟加载,因为您无法在覆盖上应用virtual关键字

如果出于某种原因,您仍然依赖IFlaggable接口,只需在基类中实现它:

public abstract class FlaggableBase<T> : IFlaggable
public抽象类FlaggableBase:IFlaggable
更新

我在VS中玩了一点,结果证明,您可以使用接口实现您想要的功能:

public interface IFlaggable<out T>
{
    T Id { get; }
    Tally Tally { get; }
    Guid? TallyId { get; }
}
公共接口IFlaggable
{
T Id{get;}
计数{get;}
Guid?TallyId{get;}
}
然后在理货课上:

public class Tally
{
    public Guid Id { get; internal set; }
    public IFlaggable<Guid> Subject { get; internal set; }
    public ICollection<Flag> Flags { get; internal set; }
}
公共类计数
{
公共Guid Id{get;内部集合;}
公共iFlagable主题{get;内部集;}
公共ICollection标志{get;internal set;}
}
以下是它在数据库中的外观:

你说EF窒息是什么意思?我已经在我的实体上使用了很多次接口。只是它不能用这样的属性创建关系。我明白为什么。实体框架无法理解“public IFlaggable Subject{get;internal set;}”属性。哦,我明白了。我没有具体做过这件事。不过,这让我很感兴趣。我真诚地希望你找到一个更好的方法。这在集合中似乎不起作用:当我使用EF检索Tall实例时,接口实体集合(此处为IFlaggables)从未填充过。一旦你将你的财产虚拟化,它将被填充。
public class Tally
{
    public Guid Id { get; internal set; }
    public IFlaggable<Guid> Subject { get; internal set; }
    public ICollection<Flag> Flags { get; internal set; }
}