我使用以下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;
}
如您所见,它调用一个返回项目ID的存储过程。它使用此ID查找Project
实体本身并将其返回。当Project
实体返回到客户端时,它将被分离。我将它附加到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";
}
此时它的实体状态为Modified
。当我提交更改时,它给出了一个关于UNIQUE KEY违规的例外,就像它试图插入它而不是更新它一样。
// At Client
_context.SubmitChanges(OnProjectSaved, a_callback);
我正在为所有操作使用相同的DomainContext
实例。为什么这不起作用?
出了什么问题?这是相当令人沮丧的。
编辑:
我试过这个(正如杰夫所建议的那样):
[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();
}
它什么都没做。它没有保存项目。
答案 0 :(得分:2)
如果在服务器端添加SaveProject方法并将对象发送回服务器以进行保存,会发生什么?
我没有使用RIA服务完成EF,但我总是将我的对象发送回服务器进行保存。我假设SubmitChanges调用你正在为你把它发送回服务器,但也许它做错了,手动处理会修复它。
答案 1 :(得分:1)
我目前没有源代码,但我看到它建议您在Silverlight中为每个操作使用新的上下文。我今天遇到了类似的问题,因为我正在使用一个服务级别的上下文,它记住了我不想要的以前的值,我改为为每个服务调用创建一个新的上下文,行为就变成了我的预期。
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;
}
}
答案 2 :(得分:1)
至于不能使用单例全局DomainContext的概念,这实际上是有争议的。在我的项目中,我使用单例DomainContext没有问题。在其他项目中,我们为应用程序中的不同模块创建了一个新的DomainContext,其中重用了实体。肯定有利有弊。看到: Strategies for Handling Your DomainContext (external blog)
答案 3 :(得分:0)
似乎问题在于,当您将项目附加到DomainContext时,它会检查_context.Projects实体集,并且找不到具有该主键的实体,然后假定新连接的实体不存在服务器端然而,提交更改应该插入它。可能的解决方法可能是将新创建的Project显式加载到DomainContext中。它将确保它在实体上设置正确的状态 - 也就是说,项目已经存在于服务器上,并且它是一个更新实例,而不是插入实例。
所以可能是这样的:
//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
}
});