使用 Linq To SQL 从 MVC3 ViewModel 更新记录
我正在尝试通过 Linq To SQL 使用 ViewModel 中的值更新数据库中的记录。我让它工作了,但它已经停止了(稍后会详细介绍)。
我有一个映射到表的客户域对象。我不需要所有字段,因此我使用 AutoMapper 将其映射到具有 Customer 字段子集的 ViewModel (CustomerEditVM)。我在服务层中执行此操作:
public CustomerEditVM GetCustomerEditVMById(int custId)
{
var domainCustomer = _repository.GetCustomerById(custId);
Mapper.CreateMap<Customer, CustomerEditVM>();
CustomerEditVM customer = Mapper.Map<Customer, CustomerEditVM>(domainCustomer);
return customer;
}
我将 CustomerEditVM ViewModel 发送到我的视图,然后用户编辑记录。在我的服务层中,我将其映射回 Customer 对象,并调用我的存储库中的 Update 方法:
public void SaveCustomer(CustomerEditVM customer)
{
Mapper.CreateMap<CustomerEditVM, Customer>();
Customer newCust = Mapper.Map<CustomerEditVM, Customer>(customer);
_repository.Update(newCust);
}
这是我的存储库和 Update 方法:
namespace AuctionAdmin.Models.Repositories
{
public interface ICustomerRepository
{
Customer GetCustomerById(int custId);
void Update(Customer customer);
}
public class CustomerRepository : ICustomerRepository
{
private AuctionAdminDataContext _dataContext;
public CustomerRepository()
{
_dataContext = new AuctionAdminDataContext();
}
public Customer GetCustomerById(int custId)
{
var customer = _dataContext.Customers.SingleOrDefault(c => c.CustomerID == custId);
return customer;
}
public void Update(Customer customer)
{
_dataContext.Customers.Attach(customer);
_dataContext.Refresh(System.Data.Linq.RefreshMode.OverwriteCurrentValues, customer);
_dataContext.SubmitChanges();
}
}
}
Update 曾经工作正常,但现在失败并出现以下错误:
无法刷新指定的对象。该对象不再存在 在数据库中。
我不知道为什么这之前工作得这么好,现在却不行,但显然我没有使用 Linq 来正确更新数据库。我应该怎么做?
谢谢
I'm trying to update a record in a database with the values in a ViewModel via Linq To SQL. I had it working but it has since stopped (more on this later).
I have a Customers domain object mapped to a table. I don't need all the fields so I use AutoMapper to map it to a ViewModel (CustomerEditVM) that has a subset of the Customer fields. I do this in my service layer:
public CustomerEditVM GetCustomerEditVMById(int custId)
{
var domainCustomer = _repository.GetCustomerById(custId);
Mapper.CreateMap<Customer, CustomerEditVM>();
CustomerEditVM customer = Mapper.Map<Customer, CustomerEditVM>(domainCustomer);
return customer;
}
I send the CustomerEditVM ViewModel to my view and the user edits the record. In my service layer I map it back to a Customer object and call the Update method in my repository:
public void SaveCustomer(CustomerEditVM customer)
{
Mapper.CreateMap<CustomerEditVM, Customer>();
Customer newCust = Mapper.Map<CustomerEditVM, Customer>(customer);
_repository.Update(newCust);
}
Here is my repository and Update method:
namespace AuctionAdmin.Models.Repositories
{
public interface ICustomerRepository
{
Customer GetCustomerById(int custId);
void Update(Customer customer);
}
public class CustomerRepository : ICustomerRepository
{
private AuctionAdminDataContext _dataContext;
public CustomerRepository()
{
_dataContext = new AuctionAdminDataContext();
}
public Customer GetCustomerById(int custId)
{
var customer = _dataContext.Customers.SingleOrDefault(c => c.CustomerID == custId);
return customer;
}
public void Update(Customer customer)
{
_dataContext.Customers.Attach(customer);
_dataContext.Refresh(System.Data.Linq.RefreshMode.OverwriteCurrentValues, customer);
_dataContext.SubmitChanges();
}
}
}
The Update used to work fine but now fails with this error:
Unable to refresh the specified object. The object no longer exists
in the database.
I'm not sure why this worked so well before and now doesn't but clearly I'm not using Linq to update the database properly. How should I be doing this?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
所以我的理解是 Automapper 并不是真正设计成以这种方式工作的。它会像您为获取视图模型所做的那样展平对象,但它实际上并没有以其他方式做事。我相信这是设计使然,因为吉米和工作人员更多地使用命令模式和消息传递将内容保存回数据库。
但是,我知道这并不能解决你的问题。所以这里有一些事情。
使用 Linq2Sql 您需要将对象拉出,然后更新它,然后保存它。这是
因为linq2sql正在跟踪对象的变化。但是,在请求之间您不再拥有 linq2sql 对象。
但是,由于 linq2sql 和 automapper 的工作方式,这很可能行不通。即使映射确实有效,linq2sql 也可能不会显示对该对象进行了更改。您最好手动绘制此图。
另外,Linq2Sql 中确实没有 Update 这样的东西。
您需要做的就是从 linq2sql 获取对象并更新它并调用 SubmitChanges();在 _dataContext 上。它会为你照顾它。我看到一些存储库接口包含 Update 方法,但它在 Linq2Sql 实现中不执行任何操作。另外,在 update 方法中调用 SubmitChanges 可能不是最好的主意,因为您可能想要更新可能的项目,然后立即提交所有更改,这就是 commitchanges 的目的(即工作单元)
So my understanding is that Automapper wasn't really designed to work this way. It flattens objects like you are doing to get your view model but it doesn't really do things the other way. I believe this is by design because Jimmy & Crew are using more of a command pattern with messaging to save things back into the database.
However, I know that doesn't solve your problem. So here are a few things.
With Linq2Sql You need to pull the object out, then update it, then save it. This is
because linq2sql is tracking the changes of the object. However, between requests you no longer have the linq2sql object.
However, that most likely won't work because of the way linq2sql and automapper work. Even if the mapping does work, linq2sql might not show that changes have been made to the object. You are going to be better off mapping this by hand.
Also, there is really no such thing as Update in Linq2Sql.
All you need to do is get the object from linq2sql update it and call SubmitChanges(); on the _dataContext. It takes care of it for you. I have seen some repository interfaces include a Update method but it doesn't do anything in a Linq2Sql implementation. Also, its probably not the best idea to call SubmitChanges in the update method as you may want to update may items then submit all the changes at once, which is kind of the purpose of submitchanges (ie unit of work)