為什麼Entity Framework試圖插入NULL?

.net entity-framework

我有兩個表,Quote和Agent。 Quote有一個名為AgentID的列,它是Agent中的外鍵。

在VS中將表添加到我的模型時,Quote類具有對Agent的引用。

在嘗試添加新報價時,我創建了一個新的報價實體,並將代理設置為:

entity.Agent = (from x in entities.AgentEntities 
    where x.AgentID == quote.AgentID select x).FirstOrDefault();

在調用SaveChanges之前,我檢查對象並查看是否已設置所有值。 Agent對象的所有值都已設置。我甚至檢查了EntityKey屬性並設置了它。

儘管存在值,但我收到此錯誤:

Cannot insert the value NULL into column 'AgentID', table 'Database.dbo.Quote'; 
column does not allow nulls. INSERT fails.

我不確定還有什麼要檢查,也許有辦法查看SQL?

編輯:我在我的應用程序中使用存儲庫模式。我在我的應用程序中使用PONO然後創建新的實體對象。當我保存新報價時,我稱之為:

public override void CreateQuote(Quote quoteToCreate)
{
  var entity = ConvertQuoteToQuoteEntity(quoteToCreate);
  entities.AddToQuoteEntities(entity);
  entities.SaveChanges();  //Error is thrown here
}

private QuoteEntity ConvertQuoteToQuoteEntity(Quote quote)
        {
            var entity = new QuoteEntity();

            if (quote != null)
            {
                entity.QuoteID = quote.QuoteID;
                entity.DiscoveryMethod = quote.DiscoveryMethod;
                entity.CompletedDateTimeStamp = quote.CompletedDateTimeStamp;
                entity.CommisionAmount = quote.CommisionAmount;
                entity.QuoteKey = quote.QuoteKey;
                entity.SelectedOption = quote.SelectedOption;
                entity.SentDateTimeStamp = quote.SentDateTimeStamp;
                entity.CustomerName = quote.CustomerName;
                entity.CustomerEmail = quote.CustomerEmail;
                entity.CustomerPrimaryPhone = quote.CustomerPrimaryPhone;
                entity.CustomerAlternatePhone = quote.CustomerAlternatePhone;
                entity.Agent = (from x in entities.AgentEntities where x.AgentID == quote.AgentID select x).First<AgentEntity>();
            }
            return entity;  //Everything looks good here (Agent is fully populated)
        }

這有點奇怪。我能夠看到生成的SQL,看起來很奇怪:

insert [dbo]。[quote]([QuoteKey],[CommisionAmount],[QuoteRequestID],[DiscoveryMethod],[SelectedOption],[CreatedDateTimeStamp],[SentDateTimeStamp],[CompletedDateTimeStamp],[CustomerName],[CustomerEmail],[ CustomerPrimaryPhone],[CustomerAlternatePhone])值(@ 0,null,null,@ 1,null,@ 2,null,null,@ 3,@ 4,@ 5,@ 6)從[QuoteID],[AgentID]中選擇[QuoteID] dbo]。[引用]其中@@ ROWCOUNT> 0和[QuoteID] = scope_identity()

熱門答案

我解決了我的問題。

讓我先說我正在使用ASP.NET MVC - 如果您正在編寫單用戶桌面應用程序,那麼您的問題可能與我的完全不同。

就我而言,我顯然已經找到了一個解決我之前遇到的問題的糟糕方案。

我正在創建我的對像上下文的多個實例 - 當您使用一個實例創建實體,並嘗試將它們與另一個實例創建的實體相關聯時,您會得到奇怪的錯誤。

為了解決這個問題,我想,好吧,我只是確保我只有一個對像上下文。所以我創建了一個帶有公共getter的類,如果尚未創建該實例,則會創建該實例並返回它。一種單例模式,確保我有一個整個應用程序的對像上下文。

在我的應用程序中,我偶爾會創建“丟棄”對象 - 例如一個臨時實體,有時會預先填充一些默認值,這樣我就可以渲染一個表單。提交表單後,將創建,填充,驗證並保存新對象。

雖然保存會失敗 - 給出此頁面上描述的錯誤,關於某些屬性為空,即使我填充了所有字段,並且實體已通過驗證。

問題是,它沒有試圖保存我剛剛創建的對象 - 它掛在上一個請求的“丟棄”對像上,並試圖先保存它。

來自PHP,讓我離開的是認識到ASP.NET MVC應用程序與PHP應用程序的生命週期截然不同。在PHP中,腳本啟動,處理請求,結束然後它們結束 - 而在ASP.NET中,它們啟動,運行一段時間,提供許多請求,然後,最終,它們結束並重新啟動。

通過在靜態方法中創建我的對像上下文,我每個請求創建的實例不是一個 - 而是每個應用程序創建一個實例。因為對像上下文在請求之間持續存在,所以我的“丟棄”實體會堆積 - 最終,當我嘗試SaveChanges()時,它當然會失敗。

這種混淆部分源於實體框架是在考慮桌面應用程序的情況下編寫的 - 它不是為Web應用程序的生命週期而設計的。

你可以解決這個問題,這是解決方案:

public class App
{
    public static MyEntities DB
    {
        get {
            // Create (as needed) and return an object context for the current Request:

            string ocKey = "MyEntities_" + HttpContext.Current.GetHashCode().ToString("x");

            if (!HttpContext.Current.Items.Contains(ocKey))
                HttpContext.Current.Items.Add(ocKey, new MyEntities());

            return HttpContext.Current.Items[ocKey] as MyEntities;
        }
    }
}

您現在可以從任何地方獲取對像上下文:

MyEntities DB = MyNamespace.App.DB;

我在這篇冗長的文章中找到了解決方案,該文章探討了管理對像上下文生命週期的幾種(正確與錯誤)方法:

http://dotnetslackers.com/articles/ado_net/Managing-Entity-Framework-ObjectContext-lifespan-and-scope-in-n-layered-ASP-NET-applications.aspx

希望這對其他人有幫助:-)



Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因