Entity Framework、SQLite和惰性加载

3
你好,我使用SQL Compact和EF4开发了一个C#预算应用程序,我通过VS2010实体数据模型模板创建了EF模型。一切运作良好。然而,我考虑开发一个iPhone应用来支持现金交易,并认为最好在两个平台上都支持后端数据库。在创建SQLite数据库和新模型后,当尝试通过我的模型中的导航属性访问引用数据时,遇到了问题。当尝试显示所引用表的属性时,我会收到NullReferenceException异常。使用以下代码时,我会在最后一行收到异常:
BudgetEntities budget = new BudgetEntities();
var accounts = budget.BankAccounts.ToList();

foreach (BankAccount a in accounts)
{
    Console.WriteLine("Name:" + a.Description);
    Console.WriteLine("Number:" + a.AccountNumber);
    Console.WriteLine("Type:" + a.BankAccountType.AccountType); //Exception occurs here.
}

奇怪的是,在这个例子中没有发生异常。我不确定发生了什么?
BudgetEntities budget = new BudgetEntities();
var accoutTypes = budget.BankAccountTypes;

var account = new BankAccount();
account.ID = Guid.NewGuid();
account.AccountTypeID = accoutTypes.First(t => t.AccountType.StartsWith("Credit")).ID;
account.BSB = "3434";
account.AccountNumber = "32323";
account.Description = "Test";
account.TrackingAccount = true;

budget.AddObject("BankAccounts", account);
budget.SaveChanges();
var accounts = budget.BankAccounts.ToList();

foreach (BankAccount a in accounts)
{
    Console.WriteLine("Name:" + a.Description);
    Console.WriteLine("Number:" + a.AccountNumber);
    Console.WriteLine("Type:" + a.BankAccountType.AccountType); //Exception doesn't happen.
}

这只是一个简单的例子,我知道可以通过在查询中添加`.Include("BankAccountTypes")`来解决它,但我有其他非常复杂的查询,这些查询创建对象并在查询中包含引用对象的属性,我不太确定如何解决这个问题。
编辑:在项目之间休息一段时间后,我回到了这个问题,最终解决了它。它与代码无关,而是与数据有关。我通过转储和加载将SQL Compact数据库转换为SQLite,并且我的Guid列数据语法错误。我以'7cee3e1c-7a2b-462d-8c3d-82dd6ae62fb4 '的形式插入Guid,实际上应该是x'7cee3e1c7a2b462d8c3d82dd6ae62fb4'。
希望我为解决这个问题掉的头发能重新长出 : )
感谢大家的参与。

这两个示例在哪里运行?Web服务器?控制台应用程序?当您在同一位置运行这两个示例时会发生什么? - tzerb
这两个示例正在运行一个简单的控制台应用程序,以尝试确定发生了什么。 - ruskie
2个回答

2
在第二个例子中,您的代码片段从以下内容开始:
var accoutTypes = budget.BankAccountTypes;

这将把所有的银行账户类型加载到您的应用程序中,您就不需要再使用懒加载了(EF会自动识别这些实体已经被加载,并修复与银行账户的关系)。

首先检查您的帐户类是否是动态代理(在调试器中检查a的类型)。如果不是,那么您在类定义中犯了一些错误,懒加载将无法工作。接下来检查您的上下文实例是否启用了延迟加载(budget.ContextOptions.LazyLoadingEnabled属性)。


我尝试将您帖子中的代码片段添加到第一个示例中,但仍然出现异常。我还检查了账户类,虽然ContextOptions.ProxyCreationEnabled设置为true并且ContextOptiions.LazyLoadingEnabled也已打开,但它不是动态代理。 - ruskie
我已经做了一些进一步的测试,并比较了为SQL Compact DB和SQLite DB创建的.edmx和.designer.cs文件,它们基本上是相同的,但是SQLite似乎无法加载引用的实体。我开始认为这是SQLite的限制。你认为这可能是这种情况吗? - ruskie
如果使用其提供程序(system.data.sqlite),则在SQLite中可能会出现一些问题,因为该提供程序针对.NET 3.5和EFv1,因此EFv4的某些功能可能不可用。 透明的延迟加载是来自EFv4的功能,但我认为它不应该依赖于提供程序,因此它应该像预期的那样仍然与旧的SQLite提供程序一起工作。 您可以尝试使用Devart的dotConnect for SQLite,并验证是否存在提供程序问题。 - Ladislav Mrnka

0
确保在BudgetEntities中声明BankAccountType属性为虚拟的。

我已经尝试过这个,但我仍然得到相同的错误。BudgetEntities是由VS2010自动生成的。我不明白为什么在使用SQL Compact DB时,使用自动生成的实体可以正常工作,而在SQLite中却不能。你有其他建议吗? - ruskie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接