2016-03-10 131 views
2

我使用LINQ和實體框架從分隔文件中導入數據,在一種情況下,EF沒有填充關鍵屬性。該類是:實體框架不填充密鑰

public class BallastType 
{ 
    public int BallastTypeId { get; set; } 
    public string Name { get; set; } 
} 

該文件包含每個條目的標題行和一行。導入它的代碼是:

var baseDir = AppDomain.CurrentDomain.BaseDirectory; 
var seedDataPath = Path.Combine(baseDir, "bin", "SeedData"); 

var ballastTypesFile = Path.Combine(seedDataPath, "BallastTypes.txt"); 
var ballastTypes = (from l in File.ReadAllLines(ballastTypesFile).Skip(1) 
    let x = l.Split('\t').ToArray() 
    select new BallastType() 
    { 
     Name = x[0] 
    }); 
context.BallastTypes.AddRange(ballastTypes); 
context.SaveChanges(); 

運行此代碼將插入所有實體,但BallastTypeId未初始化(0)。如果我在選擇後添加ToList ...

...select new BallastType() 
{ 
    Name = x[0] 
}).ToList(); 

它按預期工作並且填充BallastTypeId。有一點需要注意的是,我正在斷點處檢查它。

爲什麼添加ToList會導致EF按預期工作?我正在使用EF 6.1.3。

回答

2

如果沒有.ToList()ballastTypesIQueryable,只有在枚舉它時纔會進行評估。如果在SaveChanges之後檢查BallastTypeId的值,則實質上將重新運行LINQ語句,並重新讀取文件的內容。這意味着您在查找插入的ID時閱讀的實體不是您插入到上下文中的實體。

如果添加.ToList(),則ballastTypes將變爲列表而不是IQueryable,並且可以多次評估。

+0

感謝您的回覆。我的理解是,延遲執行只發生一次,因此一旦枚舉集合,SaveChanges必須工作,它不應該重新運行查詢表達式。 –

+0

我很確定情況並非如此。應該很容易證明 - 編寫一個調用「File.ReadAllLines(ballastTypesFile)」的函數,並且記錄一條表明它發生的消息,並將它交換到linq語句的'from'部分。 – Richard

+0

測試案例:https://dotnetfiddle.net/6j0PEe--添加一個.ToList,GetData只會運行一次,兩個對象將會一樣。 – Richard