Ali*_*hşi 6 c# design-patterns entity-framework
接口
public interface IDinnerRepository
{
IQueryable<Dinner> FindAllDinners();
IQueryable<Dinner> FindDinnersByText(string q);
Dinner GetDinner(int id);
void Add(Dinner dinner);
void Delete(Dinner dinner);
void Save();
}
Run Code Online (Sandbox Code Playgroud)
从上面的接口继承的类
public class DinnerRepository : NerdDinner.Models.IDinnerRepository
{
NerdDinnerEntities db = new NerdDinnerEntities();
Public IQueryable<Dinner> FindDinnersByText(string q)
{
return db.Dinners.Where(d => d.Title.Contains(q)
|| d.Description.Contains(q)
|| d.HostedBy.Contains(q));
}
public IQueryable<Dinner> FindAllDinners()
{
return db.Dinners;
}
public Dinner GetDinner(int id)
{
return db.Dinners.SingleOrDefault(d => d.DinnerID == id);
}
public void Add(Dinner dinner)
{
db.Dinners.AddObject(dinner);
}
public void Delete(Dinner dinner)
{
foreach (RSVP rsvp in dinner.RSVPs.ToList())
db.RSVPs.DeleteObject(rsvp);
db.Dinners.DeleteObject(dinner);
}
public void Save()
{
db.SaveChanges();
}
}
Run Code Online (Sandbox Code Playgroud)
用于程序中
public class DinnerOperation
{
DinnerRepository dr = new DinnerRepository();
// insert
public void InsertDinner()
{
Dinner dinner = dr.GetDinner(5);
dr.Dinner.Add(dinner);
dr.Save();
}
// delete
public void DeleteDinner()
{
Dinner dinner = dr.GetDinner(5);
dr.Dinner.Delete(dinner);
dr.Save();
}
}
Run Code Online (Sandbox Code Playgroud)
而且没有使用存储库设计模式......
public class DinnerOperation
{
DinnerEntities entity = new DinnerEntities();
// insert
public void InsertDinner()
{
Dinner dinner = entity.Dinners.Find(5);
entity.Dinner.Add(dinner);
entity.SaveChanges();
}
// delete
public void DeleteDinner()
{
Dinner dinner = entity.Dinners.Find(5);
entity.Dinner.Remove(dinner);
entity.SaveChanges();
}
}
Run Code Online (Sandbox Code Playgroud)
题
我不明白,在这里,为什么我们使用设计模式?以这种方式使用具有实体框架的存储库设计模式并不意味着什么.
如何将设计模式与权利框架一起使用?什么时候使用实体框架的设计模式是有意义的?
你几乎得到了它.首先,重构您的晚餐操作类,以便可以将存储库实现注入其中.
public class DinnerOperation
{
private IDinnerRepository dr;
public DinnerOperation( IDinnerRespository repository ) {
this.dr = repository;
}
// insert
public void InsertDinner()
{
Dinner dinner = dr.GetDinner(5);
dr.Dinner.Add(dinner);
dr.Save();
}
// delete
public void DeleteDinner()
{
Dinner dinner = dr.GetDinner(5);
dr.Dinner.Delete(dinner);
dr.Save();
}
}
Run Code Online (Sandbox Code Playgroud)
然后实现不同的存储库:
public class EntityFrameworkDinnerRepository : IDinnerRepository
public class NHibernateDinnerRepository : IDinnerRepository
public class Linq2SqlDinnerRepository : IDinnerRepository
public class MockDinnerRepository : IDinnerRepository
....
Run Code Online (Sandbox Code Playgroud)
然后使用您想要的任何存储库:
var repository = new ....Repository();
var operation = new DinnerOperation( repository );
operation.GetDinner(5);
Run Code Online (Sandbox Code Playgroud)
存储库用于抽象您的具体数据提供程序,从而使您的架构更加可靠.
想切换到nHibernate吗?
如果你到处都有EntityFramework,那就太痛苦了.很简单,如果您使用存储库,您只需注入另一个存储库,您的业务逻辑就不必更改.
想要对您的业务逻辑进行单元测试?
如果您坚持使用具体的数据提供商,那就太痛苦了.很简单,如果你有存储库,你只需要注入一个甚至不使用数据库的内存存储库.
现在明白了?
我在使用ORM时拒绝使用存储库模式.我认为在这种情况下它几乎没有任何好处.(是的,我希望被狂热者投票约2000次).
使用EF,我为Context创建了一个界面
public interface IDinnerContext : IDisposable
{
IDbSet<Dinner> Dinners;
int SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)
然后我将这个界面粘贴在我的EF DatabaseContext实现上,并且中提琴!我可以在任何地方使用EF,使用MOCK实现单元测试我的数据库访问,如果我愿意,可以使用注入,而不是最终使用600万个GetByXXX方法.IQeryable处理它,我得到延迟执行.我真的不需要插入/删除方法,因为IDBSet已经有添加/删除.我有更清晰/更容易阅读的代码,抽象更少.
如果我有一个案例,在许多不同的地方使用相同的查询,我真的希望这是常见的,那么我可以添加一些机制来支持它.但是,95%的情况下,查询特定于负责业务逻辑X的组件(简单GetBy语句之外的任何内容).所以我不认为这是一个问题.
不要误会我的意思,我虔诚地使用了存储库模式,直到ORM变得相当不错.一旦ORM达到一定程度的复杂程度,我觉得可能不再需要存储库模式,并且开始没有它的项目......并且永远不会回头看.我认为其他所有人最终都会朝这个方向发展,或者类似的东西,但旧的习惯会因此而死.(我知道一些仍然坚持使用锁(这个)的开发人员,因为它仍然在某些MS样本中).