簡體   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