繁体   English   中英

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

[英]Why is the Entity Framework inserting when it should update?

我使用以下 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";
} 

此时它有一个实体 state 的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();
}

它完全没有做任何事情。 它没有保存项目。

如果您在服务器端添加 SaveProject 方法并将 object 发送回服务器进行保存,会发生什么情况?

我没有使用 RIA 服务完成 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;
            }

        }

至于不能使用 singleton 全局域上下文的概念,这实际上是有争议的。 在我的项目中,我使用 singleton DomainContext 没有问题。 在其他项目中,我们为应用程序中的不同模块创建了一个新的 DomainContext 实体被重用。 肯定有好处也有坏处。 请参阅: 处理 DomainContext 的策略(外部博客)

似乎问题在于,当您将项目附加到 DomainContext 时,它会检查 _context.Projects 实体集并且没有找到具有该主键的实体,然后假定新附加的实体尚不存在服务器端并且提交更改应该插入它。 一种可能的解决方法可能是将新创建的项目显式加载到 DomainContext 中。 它将确保它在实体上设置正确的 state - 也就是说,该项目已经存在于服务器上并且它是一个更新实例,而不是一个插入实例。

所以也许是这样的:

//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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM