自从我使用 DbContext 以来已经有一段时间了。我多年来一直在使用Serivce / Repository / UnitOfWork模式,这使我能够使用实体框架而不必担心如何添加/更新和删除。
现在我已经决定使用该设计模式的某些项目不适合(主要是在使用查找表时)。因此,我已经回归基础。
使用 DbContext 已找到获取信息,但现在我已经开始创建插入/更新数据的方法,我似乎发现了一个问题。 我相当肯定这个问题很简单,但我需要一些帮助:)
这是我的方法:
[HttpPost]
[Route("")]
public IHttpActionResult Import(IList<CollectionBindingModel> models)
{
// If our ModelState is invalid, return a bad request
if (!ModelState.IsValid)
return BadRequest(ModelState);
try
{
// Loop through our models
foreach (var model in models)
{
// Create our collection
var collection = new Collection()
{
CenterId = model.CenterId,
Reference = model.Reference,
CustomerReference = model.CustomerReference,
CustomerName = model.CustomerName,
CustomerBusinessName = model.CustomerBusinessName,
SupplierName = model.SupplierName,
CollectionCode = model.CollectionCode,
Status = model.Status,
CollectionDate = model.CollectionDate
};
// Add to our database context
this.DbContext.Collections.Add(collection);
}
// Save our changes
this.DbContext.SaveChanges();
}
catch (Exception ex)
{
}
// Return Ok
return Ok();
}
我刚刚添加了try / catch块用于测试目的。 当我从我的界面调用此方法时,它返回OK并且不会抛出任何错误,但是如果我检查数据库,我看到没有插入。
谁能告诉我为什么?
更新1
所以,深入挖掘一下。我有一个基本控制器,如下所示:
/// <summary>
/// Handles the creation of universal properties and methods
/// </summary>
public class BaseController : ApiController
{
// Create our public properties
protected DatabaseContext DbContext { get { return new DatabaseContext(); } }
protected UserService UserService { get { return Request.GetOwinContext().GetUserManager<UserService>(); } }
protected RoleService RoleService { get { return Request.GetOwinContext().GetUserManager<RoleService>(); } }
protected ModelFactory ModelFactory { get { return new ModelFactory(this.Request, this.UserService); } }
/// <summary>
/// Used to return the correct error from an Identity Result
/// </summary>
/// <param name="result">The Identity Result to process</param>
/// <returns></returns>
protected IHttpActionResult GetErrorResult(IdentityResult result)
{
// If there is no result, return an internal server error
if (result == null)
return InternalServerError();
// If we have an error
if (!result.Succeeded)
{
// If we have some errors
if (result.Errors != null)
{
// For each error, add to the ModelState
foreach (var error in result.Errors)
ModelState.AddModelError("", error);
}
// If our ModelState is valid
if (ModelState.IsValid)
{
// No ModelState errors are available to send, so just return an empty BadRequest.
return BadRequest();
}
// Return a BadRequest with our ModelState
return BadRequest(ModelState);
}
// Return null if no errors are found
return null;
}
}
从哪里撤出 DbContext 。 如果我将控制器方法更改为:
[HttpPost]
[Route("")]
public IHttpActionResult Import(IList<CollectionBindingModel> models)
{
// If our ModelState is invalid, return a bad request
if (!ModelState.IsValid)
return BadRequest(ModelState);
try
{
using (var context = new DatabaseContext())
{
// Loop through our models
foreach (var model in models)
{
// Create our collection
var collection = new Collection()
{
CenterId = model.CenterId,
Reference = model.Reference,
CustomerReference = model.CustomerReference,
CustomerName = model.CustomerName,
CustomerBusinessName = model.CustomerBusinessName,
SupplierName = model.SupplierName,
CollectionCode = model.CollectionCode,
Status = model.Status,
CollectionDate = model.CollectionDate
};
// Add to our database context
context.Collections.Add(collection);
}
// Save our changes
context.SaveChanges();
}
}
catch (Exception ex)
{
return InternalServerError(ex);
}
// Return Ok
return Ok();
}
然后一切都保存好了。
答案 0 :(得分:3)
每次访问DbContext属性时,您都在新建一个DbContect。
每次访问this.DbContext时,您都会获得DbContext类的新实例,因为您已经设置了属性...
protected DatabaseContext DbContext { get { return new DatabaseContext(); } }
所以这一行得到一个新的db上下文并添加集合对象...在这个循环的下一个itteration你会得到另一个DbContext的新实例并添加下一个...你不是要添加你的集合类到相同的对象实例...
// Add to our database context
this.DbContext.Collections.Add(collection);
这也是......
// Save our changes
this.DbContext.SaveChanges();
这意味着你基本上是在一个完全没有变化的全新DbContext实例上调用保存更改。您应该始终将实体添加并附加到DbContext的同一个实例,然后再调用保存更改。
您已在新代码中修复了该问题,因为您在基类的构造函数中创建了一个新的DbContext实例,然后在整个...中使用相同的实例...
// Create our public properties
protected DatabaseContext DbContext { get; private set; }
protected UserService UserService { get { return Request.GetOwinContext().GetUserManager<UserService>(); } }
protected RoleService RoleService { get { return Request.GetOwinContext().GetUserManager<RoleService>(); } }
protected ModelFactory ModelFactory { get { return new ModelFactory(this.Request, this.UserService); } }
public BaseController()
{
this.DbContext = new DatabaseContext();
}
这也可以,当你访问属性getter时,它会返回相同的实例,如果它已被初始化...或者首先初始化它然后返回它...
private DatabaseContext _dbContext;
protected DatabaseContext DbContext
{
get { return this._dbContext ?? (this._dbContext = new DatabaseContext()); }
}
答案 1 :(得分:-1)
好的,我已经解决了这个问题,但我不明白为什么。
如果我将BaseController更改为:
/// <summary>
/// Handles the creation of universal properties and methods
/// </summary>
public class BaseController : ApiController
{
// Create our public properties
protected DatabaseContext DbContext { get; private set; }
protected UserService UserService { get { return Request.GetOwinContext().GetUserManager<UserService>(); } }
protected RoleService RoleService { get { return Request.GetOwinContext().GetUserManager<RoleService>(); } }
protected ModelFactory ModelFactory { get { return new ModelFactory(this.Request, this.UserService); } }
public BaseController()
{
this.DbContext = new DatabaseContext();
}
/// <summary>
/// Used to return the correct error from an Identity Result
/// </summary>
/// <param name="result">The Identity Result to process</param>
/// <returns></returns>
protected IHttpActionResult GetErrorResult(IdentityResult result)
{
// If there is no result, return an internal server error
if (result == null)
return InternalServerError();
// If we have an error
if (!result.Succeeded)
{
// If we have some errors
if (result.Errors != null)
{
// For each error, add to the ModelState
foreach (var error in result.Errors)
ModelState.AddModelError("", error);
}
// If our ModelState is valid
if (ModelState.IsValid)
{
// No ModelState errors are available to send, so just return an empty BadRequest.
return BadRequest();
}
// Return a BadRequest with our ModelState
return BadRequest(ModelState);
}
// Return null if no errors are found
return null;
}
}
然后一切正常。
请注意,我唯一改变的是将dbcontext的设置移动到构造函数。
我怀疑这是因为它以前的方式,每次有人请求它时都会创建一个新的数据库上下文。这次它在创建基本控制器时设置它。