LINQ to SQL - >无法访问已处置的对象。对象名:' Dispose后访问的DataContext

时间:2017-09-09 11:15:23

标签: c# linq linq-to-sql

假设我有两张桌子,即学生和学校。在我的学生表中,我有一个fkSchoolId链接到学校记录。但是,如果我检索我的记录如下

public static List<Student> GetByType(string connString, int type)
{
    using (mydb_DataContext db = new mydb_dbDataContext(connString))
    {
        return (from t1 in db.Students
                where t1.type = type
                select t1).ToList();
    }
}

我将获得Student对象列表,我可以在foreach循环中访问它。但是当我这样做时,我会在检索学校名称时收到错误。

foreach(Student student in DAL.StudentLogic.GetByType(5))
{
    string schoolName = student.School.Name;
}
  

System.ObjectDisposedException:&#39;无法访问已处置的对象。   对象名称:&#39;在Dispose之后访问的DataContext。&#39;。&#39;

我是否可以知道如何获取存储在返回对象中的外部信息以便我可以访问它们?或者更好的方法,如果我可以指定只加载学校名称?

更新: 如果我这样做,它可以工作,但不确定它将对性能产生多大影响。我将在下周再次对该主题进行基准测试和更新。

public static List<Student> GetByType(string connString, int type)
{
    using (mydb_DataContext db = new mydb_dbDataContext(connString))
    {
        List<Student> students = (from t1 in db.Students where t1.type = type select t1).ToList();

        foreach(Student student in students)
        {
            student.School.Name = db.Schools.Where(q => q.SchoolId == student.fkSchoolId).FirstOrDefault().Name;
        }
    }
}

我可以访问返回对象中的student.School.Name。

2 个答案:

答案 0 :(得分:4)

DeferredLoadingEnabled属性设置为false

  

获取或设置一个值,该值指示是否延迟加载一对多关系或一对一关系。

因此,在实现查询时将检索相关数据,而不是在稍后阶段(在上下文处理之后)检索相关数据

public static List<Student> GetByType(string connString, int type)
{
    using (mydb_DataContext db = new mydb_dbDataContext(connString))
    {
        db.DeferredLoadingEnabled = false;
        return (from t1 in db.Students
                where t1.type = type
                select t1).ToList();
    }
}

然而,考虑思考(取决于整体设计/程序要求和负载)使上下文在该类的生命周期中保持打开,此函数位于(看起来像DAL类)。然后实现IDisposable接口并在其中处置上下文。 (请记住,必须明确调用Dispose。)

如果你想要的只是学校名称而你使用的是C#7.0,你可以这样使用named tuples

public static List<(Student Student, string SchoolName)> GetByType(string connString, int type)
{
    using (mydb_DataContext db = new mydb_dbDataContext(connString))
    {
        return (from t1 in db.Students
                join school in db.Schoold on t1.SchoolId equals school.Id
                where t1.type = type
                select (t1, school.Name)).ToList();
    }
}

如果您获得compilation error CS8137,那么您需要安装System.ValueTuple

的Nuget包

答案 1 :(得分:1)

使用Linq2Sql,您可以使用LoadWith,例如

using (mydb_DataContext db = new mydb_dbDataContext(connString))
{
    DataLoadOptions op = new DataLoadOptions();
    op.LoadWith<Student>(o => o.School);

    db.LoadOptions = op;
    return (from t1 in db.Students
        where t1.type = type
        select t1).ToList();
}

一个缺点是这是检索学校表中的所有列。

相关问题