为什么在应该更新时插入实体框架?

问题描述

| 我使用以下RIA Services调用注册并返回一个“ 0”实体。
// 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查找“ 0”实体本身并返回它。当“ 0”实体返回给客户端时,它将被分离。我将它附加到
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\";
} 
此时,它的实体状态为state6ѭ。当我提交更改时,它给我一个关于UNIQUE KEY违规的例外,就好像它试图插入而不是更新它一样。
// At Client
_context.SubmitChanges(OnProjectSaved,a_callback);
我对所有操作都使用相同的“ 4”实例。为什么这不起作用? 怎么了?这相当令人沮丧。 编辑: 我尝试了这个(如杰夫建议):
[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();
}
它绝对什么也没做。它没有保存项目。     

解决方法

        如果在服务器端添加SaveProject方法并将对象发送回服务器进行保存,会发生什么情况? 我尚未使用RIA Services进行EF,但始终将我的对象发送回服务器进行保存。我假设SubmitChanges调用使您正确地整理了所有内容,以便将其发送回服务器,但也许它做错了什么,手动进行处理即可解决。     ,        我目前没有源,但是我看到它建议您为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;
            }

        }
    ,        至于不能使用单例全局DomainContext的概念,这实际上是有争议的。在我的项目中,我使用单例DomainContext没有问题。在其他项目中,我们为应用程序中重复使用实体的不同模块创建了新的DomainContext。肯定有优点和缺点。看到: 处理DomainContext的策略(外部博客)     ,        看来问题在于,当您将项目附加到DomainContext时,它会检查_context.Projects实体集,并且找不到具有该主键的实体,然后假定新附加的实体在服务器端尚不存在并且提交更改应将其插入。可能的解决方法是将新创建的项目显式加载到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
    } 
});