我最近遇到过多个数据库类型应该可以交换的问题。我的解决方案是存储库模式。 拥有这样的模型。
class Book {
public string Title { get; set; }
public virtual Author Author { get; set; }
}
class Author {
public string Name { get; set; }
public virtual ICollection<Book> Books { get; set; }
}
将这两个类作为我的模型。 以及我的存储库中的以下方法。
class AuthorRepository {
IEnumerable<Author> GetAll() {
return Context.Set<Author>().ToList();
}
}
现在我遇到了一些问题。首先是使用像这样的存储库。
using(var unitOfWork = new UnitOfWork(new MyContext())) {
MyObservableCollection = new ObservableCollection<Author>(unitOfWork.Authors.GetAll());
}
如果我尝试访问作者模型中的书籍,我会得到一个ObjectDisposedException。这很明显,因为书籍只能在DbContext中访问,因此该属性实际上只能在存储库内使用而不能在外部使用。
现在我的第二个问题是,当我想从实体框架更改为另一个持久性框架时,虚拟方法将无法工作(因为据我所知),这仅用于实体框架。
上面显示的设置是我如何看到几乎无处不在实现的存储库模式,但是当我需要在需要更改持久性框架时需要更改模型时,我看不到模式中的用法。
我的修复方法如下。
class Author {
public string Name { get; set; }
}
class EntityFrameworkAuthor : Author {
public virtual ICollection<Book> Books { get; set; }
}
EF作者只会在存储库中使用,而作者将被返回到业务层。
现在回答我的问题。
答案 0 :(得分:0)
我认为将你的模型分成两部分并不是一个好主意。就个人而言,我总是认为业务逻辑完全没有意识到持久性逻辑。
您可以通过应该以这种方式使用的存储库模式来实现:您只使用基本方法创建存储库类,然后根据需要添加新方法。 原因是您希望每个存储库都是持久层用于加载数据的机制的抽象。 (这是我发现有关存储库模式的有用的link)
我的意思是从业务层的角度来看,用于加载的方法,例如,“所有在1974年写过书的作者”可以在您的代码中实现,如存储过程或其他一切;只要请求该组数据的业务对象获得它想要的东西,它就不会(也不应该)关心。
然而,使用您的解决方案,您可以让域对象了解数据的访问方式。 就个人而言,如果将来需要能够更改ORM,我宁愿使用FacadeActorRepository,它使用一个具体的实现EfActorRepository,您可以在更改ORM时切换它。
至于延迟加载问题,在评论中以plalx为主题,(引用)
“如果数据未在业务逻辑条件下用于保护 它所属的聚合(数据集群)的状态 数据本身就可以存在,那么就不应该聚合“
这意味着如果作者真的需要一个书籍列表,你不应该允许它被延迟加载,但是你应该在创建完成作者对象后立即加载它。
我希望这会有所帮助:)