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

标签 c# linq entity-framework

我在 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/

相关文章:

c# - 警告说 Linq-To-Sql 表达式总是错误的,但这是不正确的,为什么?

c# - 使 Linq 导航属性对开发人员来说更加明显

c# - 用于打印表达式的库

c# - 如何在Java中实现类似C#的语言级事件

c# - C#中的单例类设计,这两个类是等价的吗?

c# - 使用 Entity Framework 时出现数据库错误

c# - EF核心: how to share foreign key properties between several zero/one-to-many relationships

C#:SkipLast 实现

c# - 尝试转换匿名对象 Razor 时出错

c# - 在查询之前构建 LINQ 表达式