实体框架6:使用界面作为导航属性可能吗?

Bog*_*gey 7 c# entity-framework

有没有办法在EF6中使用接口作为导航属性?我找到了EF4或更早版本的相关主题,似乎不太可能; 一般来说,从那时起,继承似乎已经有了很大的改进,但我还没有找到办法使这个特定问题发挥作用.

例:

public interface IPerson
{
  string name { get; set; }
}

public class Man : IPerson { /* ... */ }
public class Woman : IPerson { /* ... */ }

public interface ICar
{
  IPerson driver { get; set; }
}

public class Car : ICar
{
  public virtual IPerson driver { get; set; }  // This won't map
}
Run Code Online (Sandbox Code Playgroud)

这有可能吗?如果没有,那么做什么是明智的方法呢?

因为目前我没有看到任何方式让接口有一个可设置的属性,其类型是其他接口(例如ICar的IPerson属性),哪种打击我作为一个非常严重的设计限制?!

Bog*_*gey 10

好的,对于那些可能在未来面临同样问题的人.经过更多的测试,这就是我现在正在做的事情.

public interface IPerson
{
  string name { get; set; }
}

public abstract class APerson : IPerson
{
  public string name { get; set; }
}

public class Man : APerson { /* ... */ }
public class Woman : APerson { /* ... */ }

public interface ICar
{
  IPerson driver { get; set; }
}

public class Car : ICar
{
  // This maps to the database
  public virtual APerson driver { get; set; }

  // And this implements the interface
  ICar.driver
  {
    get
    {
      return (IPerson)driver;
    }
    set
    {
      if(!(value is APerson))
        throw new InvalidCastException("driver must inherit from APerson");

      driver = (APerson)value;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

当具有一对多/多对多关系时,这会变得有点棘手,对于这种情况,我编写了一个继承自Collection <Interface type>的类,但也实现了ICollection <Abstract base type>,以及当有人尝试添加/设置任何不从抽象基类继承的对象时,会再次抛出异常.它基本上是一个Collection <IPerson>,它保证只包含继承继承APerson的对象,如果你愿意的话.

这个解决方案绝对不是理想的,因为如果某人尝试为不从APerson继承的驱动程序赋值,它只会引发异常,因此这里没有编译时安全性.但是,如果你真的想让你的界面保持独立和独立,那么这是我能想到的最好的解决方案.

  • 实际上这不是一个好的设计,虽然这不是我们的错,但是EF的.我们不应该仅仅为了满足EF需求而在域中进行糟糕的设计,但现在没有别的办法.为何设计不佳?因为使用接口的想法正是为了隐藏实现细节,但我们正在通过在我们的Car中内部使用"APerson"来完全相反.如果我们的'ARobot`也是'IPerson`怎么办?如果我们有10个可能的`IPerson`怎么办?我们需要所有这些都在我们的`Car`中.所以没有必要在我们的'Car`中声明`IPerson`,但是再次,不是我们(开发人员)的错误. (3认同)
  • 我忘了补充一点,投入二传手并不是一个好主意.此外,setter中的value参数是IPerson,而不是APerson.换句话说错误是驱动程序必须实现IPerson,而不是驱动程序必须从APerson继承. (2认同)