实体框架,导航属性,存储库,工作单元,可变ORM
本文关键字:工作 单元 可变 ORM 存储 框架 导航 属性 实体 | 更新日期: 2023-09-27 17:54:33
我正试图为我的应用程序创建一个新的核心框架(主要是web),其中包含存储库和工作单元模式,我可以在以后将我的ORM更改为NHibernate或Dapper。
现在我的工作单元界面是这样的:
public interface IUnitOfWork : IDisposable
{
void Commit();
void Rollback();
}
实体框架的实现是这样的(为了可读性而修改)
public class EfUnitOfWork : IUnitOfWork
{
....
public EfUnitOfWork(ApplicationDbContext context)
{
this._context = context;
this._transaction = new EfTransaction(_context.Database.BeginTransaction());
}
public void Commit()
{
this._context.SaveChanges(true);
this._transaction.Commit();
...
}
public void Rollback()
{ ...
}
}
问题是,在包含业务逻辑的服务层中,我可以对导航属性做这样的事情:
public bool CreateCity(CityCreateModel model)
{
using (var uow = _unitOfWorkFactory.Create())
{
var city = new City();
city.Name = model.Name;
city.State = new State() { Country = new Country() { Name = "SomeCountry" }, Name = "SomeCity" };
_cityRepository.Create(city);
try
{
uow.Commit();
return true;
}
catch (Exception)
{
uow.Rollback();
throw;
}
}
}
repository Create方法非常简单,因为它使用实体框架:
public void Create(City entity)
{
_set.Add(entity);
}
问题从这里开始,当团队成员编写类似Service示例的代码,在导航属性上使用new关键字或为集合导航属性添加项时,实体框架会检测到这些更改,当我保存更改时,这些更改也会保存到数据库中。
如果我尝试将现有样本更改为Dapper。净或REST服务以后可能会有很多问题,我必须去寻找每一个导航属性和跟踪,他们已经对其进行了更改,编写大量代码(可能是垃圾)为他们正如我不知道什么是插在桌子上通过实体框架和什么不是(因为导航属性也插入我的仓库一旦只有1插入呼吁城市在我的上面的例子)
是否有一种方法可以防止这种行为,或者是否有一种已知的模式,我可以尽早适应,这样我以后就不会有问题了?
你是怎么克服的?
在我开始之前,我想给你的代码一些注释:
public EfUnitOfWork(ApplicationDbContext context)
{
this._context = context;
this._transaction = new EfTransaction(_context.Database.BeginTransaction());
}
1)从您的示例中,我可以看到您共享相同的DbContext(在整个应用程序的构造函数中作为参数给出)。我不认为这是一个好主意,因为实体将被缓存在第一层缓存中,并且更改跟踪器将跟踪它们。用这种方法会很快得到性能问题,当数据库会增长。
_cityRepository.Create(city);
public void Create(City entity)
{
_set.Add(entity);
}
2)基本存储库应该是T类型的泛型,其中T是一个实体!所以你可以创建一个城市;
var city = _cityRepository.Create();
Fill the city or provide the data as parameters in the create method.
回到你的问题:
是否有一种方法可以防止这种行为,或者是否有一种已知的模式,我可以尽早适应,这样我以后就不会有问题了?
每个ORM都有自己的设计理念,要找到适合他们的通用方法并不容易,所以我会做以下事情:
1)将存储库契约分离为一个程序集(契约dll)
2)为每个ORM框架使用一个单独的程序集来实现存储库契约。
的例子:
public interface ICityRepository<City> :IGenericRepsotiory<City>
{
City Create();
Find();
....
}
实体框架组装:
公共类CityRepositoryEF: cityrepository{. .
Dapper framework assembly:
公共类CityRepositoryDapper: cityrepository{. .
如果您遵循下面的URL,您可以找到一个精彩的介绍。它的作者Julie Lerman是一个实体框架的传道者。http://thedatafarm.com/data-access/agile-entity-framework-4-repository-part-1-model-and-poco-classes/