gpt4 book ai didi

c# - 使用 LINQ 避免 ObjectDisposedException (LINQ2SQL)

转载 作者:太空狗 更新时间:2023-10-30 01:18:28 25 4
gpt4 key购买 nike

我在 Linq 中遇到了“惰性 IO 问题”,但我还没有找到令我满意的解决方案

设置问题

假设我们有看起来像这样的 SQL 表

create table Person (
id int primary key not null,
name text not null,
)

create table Dog (
name text primary key not null,
ownerid text primary key not null references Person(name)
)

而在 C# 中,我们希望使用 LINQ 和 Entity Framework 来处理这个问题。 Entity Framework 类被定义为 partial,因此我们可以扩展它们以添加 .Get(string) 方法,这使得代码非常简洁。

public partial class Dog 
{
public static Dog Get(string dogname)
{
using (var db = new MyDataContext())
{
// LINQ is lazy and doesn't load the referenced Person
return db.Dogs.Single(d => d.name == dogname);
}
}
}

哪里出了问题

现在我们尝试使用 Dog 对象来做一些事情

public string DogJson(string dogname) 
{
var dog = Dog.Get(dogname);
return JsonConvert.SerializeObject(dog);
}

由于我们的实例 dog 包含 dog.Owner 因为有外键,JsonConvert 当然会尝试将其包含在 json 字符串中.但是由于 DataContext 被释放并且 LINQ 是惰性的,因此当然会引发 ObjectDisposedException 因为 dog.Person 在我们释放 DataContext 时没有被评估。

在这种情况下,我们根本不关心Owner对象,我们只想将Dog序列化为json。如果没有,最好的方法是什么?

我的解决方案

我有一个解决方案,但我不是特别喜欢它。使用投影到匿名对象并转换回 Dog,因为我们不允许在查询中显式构造 Dog

public static Dog Get(string dogname)
{
using (var db = new MyDataContext())
{
var tmpdog = db.Dogs.Where(d => d.name == dogname)
.Select(d => new { name = d.name, ownerid = d.ownerid}).Single();
return new Dog() { name = tmpdog.name, ownerid = tmpdog.ownerid};
}
}

我不喜欢这个解决方案,因为它不能很好地扩展。这个例子只有两个属性,很快就会失控。 LINQ 通常会生成非常优雅的代码,而这根本就不优雅。也很容易程序员

感觉我在这里采取了错误的方法。

最佳答案

我以前也遇到过这个问题,但幸运的是 Entity Framework 提供了一种简单的解决方法。您可以在查询之前禁用动态代理的延迟加载和创建。这将允许 json 序列化程序无异常地运行。

public static Dog Get(string dogname) 
{
using (var db = new MyDataContext())
{
db.Configuration.ProxyCreationEnabled = false;
db.Configuration.LazyLoadingEnabled = false;
return db.Dogs.Single(d => d.name == dogname);
}
}

关于c# - 使用 LINQ 避免 ObjectDisposedException (LINQ2SQL),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27279209/

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