我试图在MVC应用程序中使用存储库模式和EntityFramework来更新记录,但db.SaveChanges()方法不能保存到数据库。我没有收到任何错误,我可以单步执行代码,看到正确的变量传递,以及记录变量,更新。
根据我一直在阅读的内容,我认为我的问题是我有两个数据库上下文实例(MyDBEntities)。问题可能是我创建MyDBEntities实例的ReadRepository被注入到WriteRepository中,WriteRepository也创建了一个实例MyDBEntities。我不确定如何将实体注入存储库(假设我需要做的事情)。
如果我尝试在db.MyTable.Attach(record);
之前添加db.SaveChanges()
之类的内容,我会在下方收到此错误,这让我觉得我需要注入MyDBEntities()
。
An entity object cannot be referenced by multiple instances of IEntityChangeTracker.
CONTROLLER
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");
}
}
}
WRITE REPOSITORY
//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();
}
}
READ REPOSITORY
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;
}
}
答案 0 :(得分:5)
从您的 MyController 代码看起来您已经在使用Inversion of Control框架,因此请将 ReadRepository 和 WriteRepository 类更新为如下:
<强> 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 的实例来完成工作,所以您应该在那些的构造函数中指定该依赖项让您的Inversion of Control框架处理创建它而不是自己创建 MyDBEntities 的新实例。
确保在您的Inversion of Control框架的注册中,您将 MyDBEntities 实例注册为作用域或每个请求,而不是瞬态。您希望确保在每个请求中 ReadRepository 和 WriteRepository 都注入了 MyDBEntities 类的相同实例,而不是两个单独的实例就像他们现在一样。
按如下方式更新Unity配置:
<强> UnityConfig.cs 强>
在每个请求范围内向Unity注册 MyDBEntities 类。
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 ...
}