[英]In a layered architecture using Entity Framework, should I return POCO classes from the BLL? (Architecture guidance needed)
我可能读得太多了,而且还有一些信息过载。 所以我希望得到一些明确的指导。
根据我的收集,我可以使用VS2010的T4模板来生成与EF无直接关联的POCO类。 我将这些放在他们自己的项目中,而我的DAL将有一个ObjectContext派生类,对吧?
一旦我有了这些类,在UI层中使用它们是否可以接受? 也就是说,生成的类之一是BookInfo
,其中包含有关公共图书馆的书籍(标题,版本,页面,摘要等)。
我的BLL将包含一个类BooksBLL
,例如:
public class BooksBLL
{
ObjectContext _context;
public void AddBook(BookInfo book) { ... }
public void DeleteBook(int bookID) { ... }
public void UpdateBook(int bookID, BookInfo newBook) { ... }
//Advanced search taking possibly all fields into consideration
public List<BookInfo> ResolveSearch(Func<BookInfo, bool> filter) { ... }
//etc...
}
因此,我的MVVM UI应用程序中的ViewModel将与上述BLL类进行通信并交换BookInfo实例。 这样可以吗?
此外,Web上的MVVM帖子建议实现IDataErrorInfo
以进行验证。 如果我在生成的POCO类上实现所述接口可以吗? 我从样本中看到那些生成的POCO类包含所有虚拟属性和stuf,我希望添加自己的逻辑可以吗?
如果它有任何区别,目前,我的应用程序不使用WCF(或任何网络的东西)。
此外,如果您发现我正在尝试构建BLL的方式出现严重错误,请随时在该区域提供帮助。
更新(根据要求提供附加信息):
我正在尝试创建一个库自动化应用程序。 目前它不是基于网络的。
我正在考虑如下图层:
所以我想知道在ViewModel类中使用BooksBLL
的实例,在其上调用ResolveSearch()
以获取List<BookInfo>
并呈现它......也就是说,在任何地方使用POCO类。
或者我是否应该有其他类来反映从我的BLL中暴露的POCO类?
如果需要更多细节,请询问。
您正在做的基本上是Repository模式,Entity Framework和POCO非常适合。
因此,我的MVVM UI应用程序中的ViewModel将与上述BLL类进行通信并交换BookInfo实例。 这样可以吗?
这正是POCO对象的用途; 生成的类与如何手动编写它们之间没有区别。 它是您的ObjectContext,它封装了将所有更改保存回数据库的所有逻辑,并且不会直接暴露给您的UI。
我个人并不熟悉IDataErrorInfo
但如果现在你的实体只会在这个应用程序中使用,我认为没有任何理由不将它直接放在生成的类中。 如果可能的话,将它添加到T4模板将是理想的,如果错误消息遵循任何逻辑模式,它将节省您必须为每个类手动编码。
此外,如果您发现我正在尝试构建BLL的方式出现严重错误,请随时在该区域提供帮助。
这绝不是错误的,但是如果你计划针对BLL编写单元测试(我建议),你需要将ObjectContext
成员更改为IObjectContext
。 这样,您可以在运行时替换任何实现IObjectContext
接口的类(例如您的实际 ObjectContext
),这将允许您针对内存(即模拟)上下文进行测试,而不必访问数据库。
同样,考虑用某种接口替换List<BookInfo>
,例如IList<BookInfo>
或IBindingList<BookInfo>
或最小公分母IEnumerable<BookInfo>
。 这样你就不会直接绑定到特定的类List<T>
,如果你的需求随着时间而变化,这往往会发生,它将减少用其他东西替换List<BookInfo>
所需的重构,假设你有什么重新替换它实现您选择的接口。
你不需要做什么特别的事......马克说,没有“正确”的答案。 但是,如果您的应用程序非常简单,您只需复制您的类(例如BookInfoUI和BookInfoBLL),那么我建议您只使用业务类。 额外的层不会起作用,因此它不应该存在。 DDD中的Eric Evans甚至建议将所有逻辑放在UI层中,如果你的应用很简单并且业务逻辑很少。
为了区分,应用程序层应该具有对应用程序内发生的事情进行建模的类,并且域层应该具有模拟域中发生的事件的类。 例如,如果您有一个搜索页面,您的UI层可能会从应用程序层中的BookSearchService检索BookSearchResult对象列表,该列表将使用该域来提取BookInfo列表。
您的问题的答案可能取决于您的应用程序的大小和复杂性。 因此,我担心会有正确的论据来回答您的问题,也可以使用是和否。
就个人而言,我将用是的回答你的两个主要问题:
在UI层中使用POCO(域)类是否可以接受?
我想用“UI层”你实际上并不是指MVVM模式的View部分而是ViewModels。 (我相信大多数MVVM专家会反对让View直接引用模型。)
将POCO从您的Domain项目作为属性包装到ViewModel并将此包装的POCO直接绑定到View并不罕见。 最大的专业是:这很简单。 您不需要ViewModel中的其他ViewModel类或复制属性,然后在对象之间复制这些属性。
但是,如果您使用WPF,则必须考虑绑定引擎如果将它们绑定到View,将直接写入POCO属性。 这可能并不总是您想要的,特别是如果您正在使用WPF表单中的附加和更改跟踪实体。 您必须考虑取消方案或如何在取消后恢复属性,这些属性已由绑定引擎更改。
在我当前的项目中,我正在处理分离的实体:我从数据层加载POCO,从上下文中分离它,处理上下文,然后在ViewModel中使用该副本并将其绑定到View。 通过创建新上下文,通过ID从DB加载原始实体,然后从绑定到View的已更改POCO更新属性,可以在数据层中进行更新。 因此,附加实体的不受欢迎的变化问题随着这种方法而消失。 但是使用分离的entites也有缺点(例如更新更复杂)。
如果我在生成的POCO类上实现IDataErrorInfo
接口可以吗?
如果将POCO实体绑定到View(通过包装ViewModel),它不仅可以,而且如果要利用WPF绑定引擎的内置属性验证,甚至必须在POCO类上实现IDataErrorInfo
。 虽然此接口主要与UI技术一起使用,但它是System.ComponentModel
命名空间的一部分,因此不直接绑定到任何UI命名空间。 基本上IDataErrorInfo
只是一个简单的契约,它支持报告对象的状态,这也可能在UI上下文之外有用。
对于INotifyPropertyChanged
接口也是如此,如果将它们直接绑定到View,您还需要在POCO类上实现它。
出于几个架构原因,我经常会看到不同意我的意见。 但这些观点都没有说明另一种方法更容易。 如果您严格要避免在ViewModel层中使用POCO模型类,则需要添加另一个具有额外复杂性以及编程和维护工作的映射层。 所以我会投票:保持简单,只要你没有令人信服的理由和明确的好处,使你的架构更复杂。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.