【问题标题】:Entity Framework 4.1 Loose Coupling on EntitiesEntity Framework 4.1 实体上的松耦合
【发布时间】:2011-12-08 14:02:49
【问题描述】:

如果有人可以对此有所了解,请提供一些帮助。

我创建了一个代码优先的 MVC 3 应用程序,它运行良好。我现在正在重构以尽可能多地移除耦合,因为我希望域模型稍后在各种其他 MVC 3 应用程序中使用。我现在拥有的是通过规范化数据库持久化的实体集合,它们通过存储库模式进行 CRUD 编辑。我已使用 Ninject 通过控制器的构造函数来 DI 存储库,并使用 MVC 3 项目中的模型充当 DAO。

因此,在域中,我有一个名为 Case 的实体,它具有另一个案例 Client 的外键,如下所示:

public class Case : ICase
{
    [Key]
    public int CaseId { get; set; }
    public string CaseName { get; set; }
    public DateTime DateCreated { get; set; }
    public IClient Client { get; set; }
}

然后我有一个接口(该接口的存在主要是为了将它实现到视图模型以添加我的数据注释 - 我知道我可以将注释添加到域对象但正如我所说我想在其他领域使用这个域模型具有不同的通用语言的应用程序。

public interface ICase
{
    int CaseId { get; set; }
    string CaseName { get; set; }
    DateTime DateCreated { get; set; }
    IClient Client { get; set; }
}

然后我在 MVC 3 项目中有我的视图模型。

public class CaseModel : ICase
{
    [HiddenInput(DisplayValue = false)]
    int CaseId { get; set; }

    [Required(AllowEmptyStrings = false)]
    [MaxLength(100)]
    string CaseName { get; set; }

    [RegularExpression("")]
    DateTime DateCreated { get; set; }    

    IClient Client { get; set; }    
}

所以,我的第一个问题是:将 Client 的外键引用更改为 IClient 是一个新事物,它返回一个空对象。当类型是具体类时,它返回正常 - 我认为这是因为 EF4.1 尝试创建 IClient 的实例。我在这里完全错了还是有办法解决这个问题?

我的第二个问题(可能会否定我的第一个问题)是通过将数据注释添加到继承域实体接口的视图模型中,我是否也做错了什么?我应该使用模型元数据吗?如果是这样,我该如何使用元数据,以便在不触及领域的情况下使每个项目的数据注释都是唯一的?

谢谢!

【问题讨论】:

  • 只是为了澄清为什么第二个问题的解决方案可能会否定我的第一个问题。这些接口存在的唯一原因是视图模型具有类似于域实体的结构。如果有更好的方法将注释元数据添加到驻留在不同程序集中的域实体中,则不需要存在这些接口。我可以删除它们并返回使用我的域实体的具体版本。
  • 您不能在实体中使用界面作为导航参考。这就像在属性上放置一个[NotMapped] 属性,EF 只是忽略了这个属性。您必须有一个具体或抽象的类。只有集合才能使用ICollection<T> 之类的接口。另一方面,T 必须再次成为类,而不是接口。对于标准集合接口,EF 有如何实例化它们的默认规则:ICollection<T> -> HashSet<T>IList<T> -> List<T> 等。对于您自定义的接口,EF 没有这样的规则,也不知道如何实例化它们。
  • 顺便说一下 EF 现在最高到 4.2。

标签: c# interface entity-framework-4.1 data-annotations loose-coupling


【解决方案1】:

警告:我不是 EF 或 MVC3 方面的专家。

我们正在构建 EF Code First 实体,并且不打算向实体添加接口。存储库获取接口。工作单元获取接口。实体没有。存储库返回具体实体,即 POCO。实体可以耦合到相关实体。模型和其他类通常会获得存储库接口和/或注入的工作单元接口。为了测试,我们将新建一些 POCO 实体并从模拟存储库中返回它们。

我们计划将相关的 POCO 属性虚拟化,以便 EF 可以创建代理。

如果您想将视图与具体实体分离,我首先要问的是您希望从中获得什么价值。视图会被不同的实体重用吗?如果是这样,一种选择是使用AutoMapper 之类的东西来复制属性。不过,您必须注意延迟加载属性的即时访问。

【讨论】:

  • 您好,感谢您的回复!我在原始消息中试图传达的是实体的接口仅存在于具有类似结构化视图模型的目的(我在其中添加了我的应用程序指定的数据注释)。实体接口根本不是为了解耦目的。我想这么说,我的第一个问题基本上是我的错误。那么我的实际问题是,如何为指定的域实体(用于 CRUD 内容)应用程序进行数据注释,而不是将其硬编码到域中?
  • 所以您是说您不想将 MVC HiddenInputAttribute 放在实体上,对吗?我同意这一点。我会把它们留在 ViewModel 上。将您的实体复制到您的 ViewModel(手动或使用 AutoMapper),或者只是让您的 ViewModel 委托给实体(这可能会更好)。同样,我不是该模式的专家 - Wikipedia article 似乎使用委托。
  • 如果您指的是 EF 特定的属性,例如 MaxLength,我会说“那又如何 - 如果我们放弃 EF,我们会遇到其他问题”,或者使用 Fluent API 在不同的班级。
  • 我确实开始手动将我的域实体的属性复制到视图模型 - 但后来停止了,因为我认为必须有更好的方法来做到这一点。我会研究 AutoMapper,还没有使用过。您是否知道在 MVC 项目中定义元数据类并以某种方式将其绑定到当前上下文中的域实体的任何方法?
  • 我很确定会到达我想去的地方,我将不得不使用您之前的建议,即手动将我的域对象的属性复制到项目中的视图模型。这样我至少可以将我的数据注释与我的域分开,任何作为 POST 模型存在的视图模型都将使用 AutoMapper 来同步属性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-09
相关资源
最近更新 更多