gpt4 book ai didi

c# - Entity Framework ICollection 导航属性仅在测试时为 null

转载 作者:太空宇宙 更新时间:2023-11-03 23:14:35 25 4
gpt4 key购买 nike

我在 MVC 5 项目中使用 Entity Framework 6.1.3,并且在单元测试时我遇到了 ICollection 导航属性为 null 的问题。我正在使用 SQL Express 访问一个实际的测试数据库,所以这可能更像是对纯粹主义者的集成测试。不管你怎么调用它,它都是我想解决的问题。

我读过很多类似问题的答案,但似乎没有一个能解决我在这里遇到的同样问题。我在很大程度上理解 EF,我启用了延迟加载,我的类是公共(public)的,并且我在我的导航属性上使用了 virtual

这是我正在尝试做的一个简化示例:

模型:

public class Session
{
public int Id { get; set; }
public string Name { get; set; }

// Navigation Property
public virtual ICollection<File> Files { get; set; }
}

public class File
{
public int Id { get; set; }
public string Name { get; set; }

public int SessionId { get; set; }
public virtual Session Session { get; set; }
}

测试方法:

[TestMethod]
public void Test_TotalFileCount1()
{
ApplicationDbContext context = new ApplicationDbContext();

// Create session with no files
var session = new Session() { Name = "Session1" };
context.Sessions.Add(session);
context.SaveChanges();

// This line blows up because session.Files == null
Assert.AreEqual(0, session.Files.Count);
}

[TestMethod]
public void Test_TotalFileCount2()
{
ApplicationDbContext context = new ApplicationDbContext();

// Create session
var session = new Session() { Name = "Session2" };
context.Sessions.Add(session);
context.SaveChanges();

// Create file for session
var file = new File() { Name = "File1", Session = session };
context.Files.Add(file)
context.SaveChanges();

// This test passes because session.Files is a
// collection of one file
Assert.AreEqual(1, session.Files.Count);
}

上面的第一个测试失败,因为 session.Files 抛出 ArgumentNullException。但是,当我在完整的 MVC 应用程序中调用相同的代码时,session.Files 不是空的,而是一个 Count = 0 的空集合。第二个测试通过了,因为 session.Files 正如我所期望的那样是一个 File 的集合。在第二种情况下,导航属性显然在做它们应该做的事情,但在第一种情况下却没有。

为什么 EF 会这样?

我能够通过在构造函数中将 Files 初始化为一个空列表来解决这个问题。我知道我可以在 getter 中有条件地执行此操作,但我认为我不必执行这些操作中的任何一个,因为它只在正常运行时起作用。

public Session()
{
this.Files = new List<File>();
}

有没有人知道这里发生了什么?

最佳答案

如果您在启用延迟加载的情况下工作,并且如果您希望在将具有外键属性的对象添加到上下文后填充导航属性,您必须使用 DbSet 的 Create 方法(而不是使用 new 实例化对象) :

var session = context.Sessions.Create();

通过主动延迟加载,这将创建一个代理对象,以确保加载导航属性。

[TestMethod]
public void Test_TotalFileCount1()
{
ApplicationDbContext context = new ApplicationDbContext();

// Create session with no files
var session = context.Sessions.Create();
session.Name = "Session1";

context.Sessions.Add(session);
context.SaveChanges();

// This line blows up because session.Files == null
Assert.AreEqual(0, session.Files.Count);
}

[TestMethod]
public void Test_TotalFileCount2()
{
ApplicationDbContext context = new ApplicationDbContext();

// Create session
var session = context.Sessions.Create();
session.Name = "Session2";
session.Files = new List<File>()
{
new File() { Name = "File1" }
};

context.Sessions.Add(session);
context.SaveChanges();


// This test passes because session.Files is a
// collection of one file
Assert.AreEqual(1, session.Files.Count);
}

查看更多关于 Proxies 的信息

关于c# - Entity Framework ICollection 导航属性仅在测试时为 null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37689966/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com