在Entity Framework中存储基于接口的关系
我有我想要实现的这个领域设计理念。 我使用实体框架作为存储机制,我看到这样做的唯一方式似乎并不理想。
我有很多域对象,其中许多需要“可标记”。 用户需要能够以某种方式“标记”它们中的每一个,因为需要注意。
所以我想我会创建这个接口:
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; }
}
如果这不明显,FlagIndication是一个枚举。
然后所有其他域对象所要做的就是实现IFlaggable,并且它们成为可标记的。
public class TestFlaggable : IFlaggable
{
public Guid Id { get; internal set; }
public Tally Tally { get; internal set; }
public Guid? TallyId { get; internal set; }
}
看起来很棒。 就数据库而言,它应该工作得很好,因为它是一对一的关系,其他表总是包含一个外键给Tallies表的id字段。
麻烦的是实体框架需要查看界面和扼流圈。 明显。 我们知道实体框架不能很好地与界面配合。
我可以看到使它与Entity Framework一起工作的唯一方法是通过取消界面,创建子类,如从Tally继承的“TestFlaggableTally”,然后每个其他对象都可以拥有它自己的特殊雪花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; }
}
这应该工作,但它似乎愚蠢和臃肿。
所以,我在这里问。 有没有更好的办法?
我有一些根本的误解吗?
这是我最好的选择吗?
好吧,打我
我认为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; }
}
请注意,我将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; }
}
使用抽象类而不是接口的唯一缺点是我马上就会看到,您将无法利用延迟加载,因为您无法在覆盖上应用虚拟关键字。
如果出于某种原因,您仍然依赖IFlaggable接口,只需在基类中实现它:
public abstract class FlaggableBase<T> : IFlaggable
UPDATE
我在VS中玩过一段时间,结果你实际上可以用接口来做你想做的事情:
public interface IFlaggable<out T>
{
T Id { get; }
Tally Tally { get; }
Guid? TallyId { get; }
}
然后在你的Tally课堂上:
public class Tally
{
public Guid Id { get; internal set; }
public IFlaggable<Guid> Subject { get; internal set; }
public ICollection<Flag> Flags { get; internal set; }
}
以下是它在数据库中的外观:
链接地址: http://www.djcxy.com/p/22629.html上一篇: Storing an interface based relationship in Entity Framework
下一篇: list<T>?