[英]Why is the Entity Framework inserting when it should update?
I use the following RIA Services call to register and return a Project
entity.我使用以下 RIA 服务调用来注册并返回一个Project
实体。
// On Server; inside RIA Domain Service
[Invoke]
public Project CreateNewProject(String a_strKioskNumber)
{
Decimal dProjectID = ObjectContext.RegisterProjectNumber(a_strKioskNumber)
.FirstOrDefault() ?? -1m;
// Tried this but it returned zero (0)
//int nChanged = ObjectContext.SaveChanges();
var project = (from qProject in ObjectContext.Projects.Include("ProjectItems")
where qProject.ID == dProjectID
select qProject)
.FirstOrDefault();
if (project == null)
return null;
return project;
}
As you can see, it calls a stored procedure that returns a project ID.如您所见,它调用了一个返回项目 ID 的存储过程。 It uses this ID to look up the Project
entity itself and return it.它使用此 ID 来查找Project
实体本身并返回它。 When the Project
entity is returned to the client it is detached.当Project
实体返回给客户端时,它会被分离。 I attach it to the DomainContext
and modify it.我将它附加到DomainContext
并修改它。
// At Client
_activeProject = a_invokeOperation.Value; // <-- Detached
_context.Projects.Attach(_activeProject); // <-- Unmodified
if (_activeProject != null)
{
_activeProject.AuthenticationType = "strong"; // <-- Modified
_activeProject.OwnerID = customer.ID;
_projectItems.Do(pi => _activeProject.ProjectItems.Add(pi));
_activeProject.Status = "calculationrequired";
}
At this point it has an entity state of Modified
.此时它有一个实体 state 的Modified
。 When I submit changes it gives me an exception regarding a UNIQUE KEY violation as if it is trying to insert it rather than update it.当我提交更改时,它会给我一个关于 UNIQUE KEY 违规的异常,就好像它试图插入它而不是更新它一样。
// At Client
_context.SubmitChanges(OnProjectSaved, a_callback);
I'm using the same DomainContext
instance for all operations.我对所有操作使用相同的DomainContext
实例。 Why should this not work?为什么这不起作用?
What's going wrong?怎么了? This is rather frustrating.这是相当令人沮丧的。
Edits:编辑:
I tried this (as suggested by Jeff):我试过这个(正如杰夫所建议的那样):
[Invoke]
public void SaveProject(Project a_project)
{
var project = (from qProject in ObjectContext.Projects
where qProject.ID == a_project.ID
select qProject)
.FirstOrDefault();
project.SubmitDate = a_project.SubmitDate;
project.PurchaseDate = a_project.PurchaseDate;
project.MachineDate = a_project.MachineDate;
project.Status = a_project.Status;
project.AuthenticationType = a_project.AuthenticationType;
project.OwnerID = a_project.OwnerID;
project.ProjectName = a_project.ProjectName;
project.OwnerEmail = a_project.OwnerEmail;
project.PricePerPart = a_project.PricePerPart;
project.SheetQuantity = a_project.SheetQuantity;
project.EdgeLength = a_project.EdgeLength;
project.Price = a_project.Price;
project.ShipToStoreID = a_project.ShipToStoreID;
project.MachiningTime = a_project.MachiningTime;
int nChangedItems = ObjectContext.SaveChanges();
}
It did absolutely nothing.它完全没有做任何事情。 It didn't save the project.它没有保存项目。
What happens if you add a SaveProject method on the server side and send the object back to the server for saving?如果您在服务器端添加 SaveProject 方法并将 object 发送回服务器进行保存,会发生什么情况?
I've not done EF with RIA Services, but I've always sent my objects back to the server for saving.我没有使用 RIA 服务完成 EF,但我总是将我的对象发送回服务器进行保存。 I'm assuming that SubmitChanges call you are making wires up everything properly for you for sending it back to the server, but perhaps it is doing something wrong and handling it manually will fix it.我假设 SubmitChanges 调用您正在为您正确连接所有内容以将其发送回服务器,但也许它做错了什么并且手动处理它会修复它。
I dont have the source at the moment but I have seen it recommended that you use a new context for each operation in Silverlight.我目前没有源代码,但我看到它建议您为 Silverlight 中的每个操作使用新的上下文。 I ran into a similar problem today and it was because I was using a Service level context that was remembering previous values that I didnt want, I changed to creating a new context for each service call and the behavior became what I expected.我今天遇到了类似的问题,这是因为我使用了一个服务级别的上下文,它记住了我不想要的以前的值,我改为为每个服务调用创建一个新的上下文,并且行为变成了我的预期。
public void SaveResponses(ICollection<Responses> items, Action<SubmitOperation> callback)
{
try
{
SurveysDomainContext _context = new SurveysDomainContext();
foreach (Responses item in items)
{
_context.Responses.Add(item);
}
_context.SubmitChanges(callback, null);
}
catch (Exception)
{
throw;
}
}
As for the notion that one can't use a singleton global DomainContext, this is actually debatable.至于不能使用 singleton 全局域上下文的概念,这实际上是有争议的。 In my project I use a singleton DomainContext with no issues.在我的项目中,我使用 singleton DomainContext 没有问题。 In other projects, we have created a new DomainContext for different modules in the app where the entities are reused.在其他项目中,我们为应用程序中的不同模块创建了一个新的 DomainContext 实体被重用。 There are definitely pros and cons.肯定有好处也有坏处。 See: Strategies for Handling Your DomainContext (external blog)请参阅: 处理 DomainContext 的策略(外部博客)
It seems that the problem is that when you attach your project to the DomainContext it checks the _context.Projects entityset and isn't finding an entity with that primary key, and then assumes that the newly attached entity doesn't exist serverside yet and that submitting changes should insert it.似乎问题在于,当您将项目附加到 DomainContext 时,它会检查 _context.Projects 实体集并且没有找到具有该主键的实体,然后假定新附加的实体尚不存在服务器端并且提交更改应该插入它。 A possible workaround might be to explicitly load the newly created Project into the DomainContext.一种可能的解决方法可能是将新创建的项目显式加载到 DomainContext 中。 It would ensure that it sets the correct state on the entity--that is, that the project already exists on the server and that that it's an update instance, rather than an insert instance.它将确保它在实体上设置正确的 state - 也就是说,该项目已经存在于服务器上并且它是一个更新实例,而不是一个插入实例。
So maybe something like:所以也许是这样的:
//after your Project has already been created serverside with the invoke
_context.Load(_context.SomeQueryThatLoadsYourNewlyCreatedProject(), LoadBehavior.RefreshCurrent, (LoadOperation lo) => {
Project project = lo.Entities.FirstOrDefault(); //is attached and has correct state
if (project != null)
{
project.AuthenticationType = "strong";
project.OwnerID = customer.ID;
project.Do(pi => _activeProject.ProjectItems.Add(pi));
project.Status = "calculationrequired";
_context.SubmitChanges(); //hopefully will trigger an update, rather than an insert
}
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.