具有 Entity Framework 和更新记录的 MVC 存储库模式
MVC Repository Pattern with Entity Framework and Updating a Record
我正在尝试在 MVC 应用程序中使用带有 EntityFramework 的存储库模式来更新记录,但是 db.SaveChanges() 方法没有保存到数据库中。我没有收到任何错误,我可以单步执行代码并查看传递的正确变量以及更新的记录变量。
根据我一直在阅读的内容,我相信我的问题是我有两个数据库上下文实例 (MyDBEntities)。问题可能是创建 MyDBEntities 实例的我的 ReadRepository 被注入到 WriteRepository 中,WriteRepository 也创建了一个 MyDBEntities 实例。我不太确定如何将实体注入存储库(假设这是我需要做的)。
如果我尝试在 db.SaveChanges()
之前添加类似 db.MyTable.Attach(record);
的内容,我会在下面收到此错误,这让我觉得我需要注入 MyDBEntities()
.
An entity object cannot be referenced by multiple instances of IEntityChangeTracker.
控制器
public class MyController : Controller
{
private IWriteRepository _writeRepository;
public MyController(IWriteRepository writeRepository)
{
_writeRepository = writeRepository;
}
[HttpPost]
public ActionResult MyPostMethod(MyViewModel model)
{
try
{
//Send to the repository to edit a record
writeRepository.EditRecord(model);
return new HttpStatusCodeResult(HttpStatusCode.OK);
}
catch
{
throw new HttpException(500, "Internal Server Error");
}
}
}
写入存储库
//The ReadRepository is injected into the WriteRepository to grab records from the database
public class WriteRepository : IWriteRepository
{
private MyDBEntities db = new MyDBEntities();
private IReadRepository _readRepository;
public WriteRepository(IReadRepository readeadRepository)
{
_readRepository = readRepository;
}
public void EditRecord(MyViewModel model)
{
//Get the specific record to be updated
var record = readRepository.GetRecord(model.ID);
//Update the data
record.FirstName = model.Name;
//This isn't saving
db.SaveChanges();
}
}
阅读存储库
public class ReadRepository : IReadRepository
{
private MyDBEntities db = new MyDBEntities();
//Provides the record to the write repository to edit
public MyTable GetRecord(int ID)
{
var record = (from t in db.MyTable
where t.ID == ID
select t).SingleOrDefault();
return record;
}
}
从您的 MyController 代码看来您已经在使用控制反转框架,因此请更新您的 ReadRepository 和 WriteRepository class如下:
ReadRepository
public class ReadRepository : IReadRepository
{
private MyDBEntities db;
public ReadRepository(MyDBEntities myDbEntities)
{
db = myDbEntities;
}
//Provides the record to the write repository to edit
public MyTable GetRecord(int ID)
{
var record = (from t in db.MyTable
where t.ID == ID
select t).SingleOrDefault();
return record;
}
}
WriteRepository
public class WriteRepository : IWriteRepository
{
private MyDBEntities db;
private IReadRepository _readRepository;
public WriteRepository(MyDBEntities myDbEntities, IReadRepository readeadRepository)
{
db = myDbEntities;
_readRepository = readRepository;
}
public void EditRecord(MyViewModel model)
{
//Get the specific record to be updated
var record = readRepository.GetRecord(model.ID);
//Update the data
record.FirstName = model.Name;
//This isn't saving
db.SaveChanges();
}
}
你的 ReadRepository 和 WriteRepository 都依赖于 MyDBEntities 的一个实例来工作,因此,您应该在那些 classes 的构造函数中指定该依赖项,并让您的控制反转框架处理创建它,而不是自己创建 MyDBEntities 的新实例。
确保在您的控制反转框架的注册中,您将 MyDBEntities 实例注册为作用域或每个请求,而不是瞬态的。您要确保在每个请求中,您的 ReadRepository 和 WriteRepository 都注入了 MyDBEntities[= 的相同实例50=] class 而不是像现在这样两个单独的实例。
按如下方式更新您的 Unity 配置:
UnityConfig.cs
在每个请求范围内向 Unity 注册您的 MyDBEntities class。
public class UnityConfig
{
// ... other methods ...
public static void RegisterTypes(IUnityContainer container)
{
// ... other registrations ...
container.RegisterType<IReadRepository, ReadRepository>();
container.RegisterType<IWriteRepository, WriteRepository>();
container.RegisterType<MyDBEntities>(new PerRequestLifetimeManager());
// ... other registrations ...
}
}
UnityMvcActivator.cs
通过取消注释 TODO 下的行,在 Unity 中启用每个请求范围。
public static class UnityWebActivator
{
public static void Start()
{
// ... start code ...
// TODO: Uncomment if you want to use PerRequestLifetimeManager
Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
}
// ... other methods ...
}
我正在尝试在 MVC 应用程序中使用带有 EntityFramework 的存储库模式来更新记录,但是 db.SaveChanges() 方法没有保存到数据库中。我没有收到任何错误,我可以单步执行代码并查看传递的正确变量以及更新的记录变量。
根据我一直在阅读的内容,我相信我的问题是我有两个数据库上下文实例 (MyDBEntities)。问题可能是创建 MyDBEntities 实例的我的 ReadRepository 被注入到 WriteRepository 中,WriteRepository 也创建了一个 MyDBEntities 实例。我不太确定如何将实体注入存储库(假设这是我需要做的)。
如果我尝试在 db.SaveChanges()
之前添加类似 db.MyTable.Attach(record);
的内容,我会在下面收到此错误,这让我觉得我需要注入 MyDBEntities()
.
An entity object cannot be referenced by multiple instances of IEntityChangeTracker.
控制器
public class MyController : Controller
{
private IWriteRepository _writeRepository;
public MyController(IWriteRepository writeRepository)
{
_writeRepository = writeRepository;
}
[HttpPost]
public ActionResult MyPostMethod(MyViewModel model)
{
try
{
//Send to the repository to edit a record
writeRepository.EditRecord(model);
return new HttpStatusCodeResult(HttpStatusCode.OK);
}
catch
{
throw new HttpException(500, "Internal Server Error");
}
}
}
写入存储库
//The ReadRepository is injected into the WriteRepository to grab records from the database
public class WriteRepository : IWriteRepository
{
private MyDBEntities db = new MyDBEntities();
private IReadRepository _readRepository;
public WriteRepository(IReadRepository readeadRepository)
{
_readRepository = readRepository;
}
public void EditRecord(MyViewModel model)
{
//Get the specific record to be updated
var record = readRepository.GetRecord(model.ID);
//Update the data
record.FirstName = model.Name;
//This isn't saving
db.SaveChanges();
}
}
阅读存储库
public class ReadRepository : IReadRepository
{
private MyDBEntities db = new MyDBEntities();
//Provides the record to the write repository to edit
public MyTable GetRecord(int ID)
{
var record = (from t in db.MyTable
where t.ID == ID
select t).SingleOrDefault();
return record;
}
}
从您的 MyController 代码看来您已经在使用控制反转框架,因此请更新您的 ReadRepository 和 WriteRepository class如下:
ReadRepository
public class ReadRepository : IReadRepository
{
private MyDBEntities db;
public ReadRepository(MyDBEntities myDbEntities)
{
db = myDbEntities;
}
//Provides the record to the write repository to edit
public MyTable GetRecord(int ID)
{
var record = (from t in db.MyTable
where t.ID == ID
select t).SingleOrDefault();
return record;
}
}
WriteRepository
public class WriteRepository : IWriteRepository
{
private MyDBEntities db;
private IReadRepository _readRepository;
public WriteRepository(MyDBEntities myDbEntities, IReadRepository readeadRepository)
{
db = myDbEntities;
_readRepository = readRepository;
}
public void EditRecord(MyViewModel model)
{
//Get the specific record to be updated
var record = readRepository.GetRecord(model.ID);
//Update the data
record.FirstName = model.Name;
//This isn't saving
db.SaveChanges();
}
}
你的 ReadRepository 和 WriteRepository 都依赖于 MyDBEntities 的一个实例来工作,因此,您应该在那些 classes 的构造函数中指定该依赖项,并让您的控制反转框架处理创建它,而不是自己创建 MyDBEntities 的新实例。
确保在您的控制反转框架的注册中,您将 MyDBEntities 实例注册为作用域或每个请求,而不是瞬态的。您要确保在每个请求中,您的 ReadRepository 和 WriteRepository 都注入了 MyDBEntities[= 的相同实例50=] class 而不是像现在这样两个单独的实例。
按如下方式更新您的 Unity 配置:
UnityConfig.cs
在每个请求范围内向 Unity 注册您的 MyDBEntities class。
public class UnityConfig
{
// ... other methods ...
public static void RegisterTypes(IUnityContainer container)
{
// ... other registrations ...
container.RegisterType<IReadRepository, ReadRepository>();
container.RegisterType<IWriteRepository, WriteRepository>();
container.RegisterType<MyDBEntities>(new PerRequestLifetimeManager());
// ... other registrations ...
}
}
UnityMvcActivator.cs
通过取消注释 TODO 下的行,在 Unity 中启用每个请求范围。
public static class UnityWebActivator
{
public static void Start()
{
// ... start code ...
// TODO: Uncomment if you want to use PerRequestLifetimeManager
Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
}
// ... other methods ...
}