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

tea*_*eng 3 c# linq linq-to-sql

假设我有 2 张桌子,分别是学生和学校。在我的学生表中,我有一个链接到学校记录的 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

我将拥有可以在 foreach 循环中访问的 Student 对象列表。但是当我做如下操作时,在检索学校名称时会出错。

foreach(Student student in DAL.StudentLogic.GetByType(5))
{
    string schoolName = student.School.Name;
}
Run Code Online (Sandbox Code Playgroud)

System.ObjectDisposedException: '无法访问已处理的对象。对象名称:'DataContext 在 Dispose 后访问。'。

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

更新:如果我按照以下操作,它会起作用,但不确定它会对性能产生多大影响。下周我将做一个基准测试并再次更新这个主题。

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我将能够在我的返回对象中访问 student.School.Name。

Gil*_*een 5

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,请考虑考虑(取决于整体设计/程序要求和负载)让上下文在该函数所在的类的生命周期内保持打开状态(看起来像一个 DAL 类)。然后实现IDisposable接口并在其中处理上下文。(请记住,Dispose必须显式调用)。


如果您只需要学校名称并且您使用的是 C# 7.0,则可以这样使用命名元组

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

如果你得到编译错误 CS8137那么你需要安装 Nuget 包System.ValueTuple