C# 实体框架未填充密钥

C# 实体框架未填充密钥,c#,entity-framework,linq,C#,Entity Framework,Linq,我使用LINQ和实体框架从一个分隔文件导入数据,在一个场景中EF没有填充key属性。课程为: public class BallastType { public int BallastTypeId { get; set; } public string Name { get; set; } } 该文件包含一个标题行和每个条目的一行。要导入它的代码是: var baseDir = AppDomain.CurrentDomain.BaseDirectory; var seedDat

我使用LINQ和实体框架从一个分隔文件导入数据,在一个场景中EF没有填充key属性。课程为:

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。

没有
.ToList()
ballastTypes
是一个
IQueryable
,只有在您枚举它时才会进行计算。如果在
SaveChanges
之后检查
BallastTypeId
的值,则实际上是在重新运行LINQ语句,并重新读取文件的内容。这意味着在查找插入的ID时读取的实体不是插入到上下文中的实体


如果您添加一个
.ToList()
,则
ballastTypes
将变成一个列表,而不是
IQueryable
,并且可以进行多次计算。

感谢您的回复。我的理解是,延迟执行只发生一次,因此一旦枚举了集合(SaveChanges必须执行该集合),它就不应该重新运行查询表达式。我很确定情况并非如此。应该很容易证明-编写一个调用
File.ReadAllLines(ballastTypesFile)
的函数,并记录一条指示发生了这种情况的消息,然后将其从linq语句的
部分交换到
中。测试用例:-添加一个.ToList和GetData只运行一次,这两个对象是相同的。不确定这是一个有效的测试用例(),但它模仿了我在查询真实数据库时经常看到的LINQ行为:查询执行一次。说清楚一点,我知道这与延迟执行有关,我只是想理解它。我认为这是你最初问题中的“让”中间步骤,它阻止它知道只执行一次。在最初的问题中,您的File.ReadAllLines执行了两次(断点可能会确认这一点)。