c# – 为什么我的代码执行懒惰加载,即使我把它关闭在所有可能的点?

c# – 为什么我的代码执行懒惰加载,即使我把它关闭在所有可能的点?,第1张

概述我想获得具有UserId的等级为“0”的UserTest实体的考试和测试实体或提供的值.我有一些建议,但到目前为止还没有工作.有一个建议是从获取UserTest数据开始,另一个解决方案是从获取考试数据开始.当我使用UserTests作为源起点时,这是我所用的. 我有以下LINQ: var userTests = _uow.UserTests .GetAll() 我想获得具有UserID的等级为“0”的UserTest实体的考试和测试实体或提供的值.我有一些建议,但到目前为止还没有工作.有一个建议是从获取UserTest数据开始,另一个解决方案是从获取考试数据开始.当我使用UserTests作为源起点时,这是我所用的.

我有以下liNQ:

var userTests = _uow.UserTests            .GetAll()            .Include(t => t.Test)            .Include(t => t.Test.Exam)            .Where(t => t.UserID == "0" || t.UserID == userID)            .ToList();

当我使用调试器检查_uow.UserTests时,它是一个存储库,当我检查dbcontext的configuration.lazyloading时,它被设置为false.

这是我的课程:

public class Exam{    public int ExamID { get; set; }    public int SubjectID { get; set; }    public string name { get; set; }    public virtual ICollection<Test> Tests { get; set; }}public class Test{    public int TestID { get; set; }    public int ExamID { get; set; }    public string Title { get; set; }    public virtual ICollection<UserTest> UserTests { get; set; }}public class UserTest{    public int UserTestID { get; set; }    public string UserID { get; set; }    public int TestID { get; set; }    public int QuestionsCount { get; set; }}

当我看着输出时,我看到这样的东西:

[{"userTestID":2,"userID":"0","testID":12,"test":{      "testID":12,"examID":1,"exam":{          "examID":1,"subjectID":1,"tests":[               {"testID":13,"Title":"Sample Test1","userTests":[                      {"userTestID":3,

请注意,它获取一个UserTest对象,然后获取一个测试对象,然后获取一个考试对象.然而,考试对象包含一个测试集合,然后再次返回,并获得不同的测试和单元测试:

UserTest>测试>考试>测试> UserTest?

我已经努力确保懒惰加载关闭和调试告诉我它被设置为假.我正在使用EF6和WebAPI,但不知道如果这是有区别的,因为我正在调试C#级别.

解决方法 您不能避免反向导航属性由EF填充,无论您是否加载相关的实体加载或加载.这个关系fixup(已经由@Colin解释)是一个您无法关闭的功能.

您可以通过在查询完成后取消未完成的反向导航属性来解决问题:

foreach (var userTest in userTests){    if (userTest.Test != null)    {        userTest.Test.UserTests = null;        if (userTest.Test.Exam != null)        {            userTest.Test.Exam.Tests = null;        }    }}

然而,在我看来,您的设计的缺陷是您尝试将实体序列化,而不是将数据专用于要发送数据的视图的数据传输对象(“DTO”).通过使用DTO,您可以避免不需要的反向导航属性,也可以避免您在视图中不需要的其他实体属性.您将定义三个DTO类,例如:

public class ExamDTO{    public int ExamID { get; set; }    public int SubjectID { get; set; }    public string name { get; set; }    // no Tests collection here}public class TestDTO{    public int TestID { get; set; }    public string Title { get; set; }    // no UserTests collection here    public ExamDTO Exam { get; set; }}public class UserTestDTO{    public int UserTestID { get; set; }    public string UserID { get; set; }    public int QuestionsCount { get; set; }    public TestDTO Test { get; set; }}

然后使用投影来加载数据:

var userTests = _uow.UserTests    .GetAll()    .Where(ut => ut.UserID == "0" || ut.UserID == userID)    .Select(ut => new UserTestDTO    {        UserTestID = ut.UserTestID,UserID = ut.UserID,QuestionsCount = ut.QuestionsCount,Test = new TestDTO        {            TestID = ut.Test.TestID,Title = ut.Test.Title,Exam = new ExamDTO            {                ExamID = ut.Test.Exam.ExamID,SubjectID = ut.Test.Exam.SubjectID,name = ut.Test.Exam.name            }        }    })    .ToList();

您还可以通过仅定义一个包含视图所需的所有属性的单个DTO类来“展平”对象图:

public class UserTestDTO{    public int UserTestID { get; set; }    public string UserID { get; set; }    public int QuestionsCount { get; set; }    public int TestID { get; set; }    public string TestTitle { get; set; }    public int ExamID { get; set; }    public int ExamSubjectID { get; set; }    public string Examname { get; set; }}

投影将变得更简单,如下所示:

var userTests = _uow.UserTests    .GetAll()    .Where(ut => ut.UserID == "0" || ut.UserID == userID)    .Select(ut => new UserTestDTO    {        UserTestID = ut.UserTestID,TestID = ut.Test.TestID,TestTitle = ut.Test.Title,ExamID = ut.Test.Exam.ExamID,ExamSubjectID = ut.Test.Exam.SubjectID,Examname = ut.Test.Exam.name    })    .ToList();

通过使用DTO,您不仅可以避免反向导航属性的问题,还可以遵循良好的安全措施,从而明确地从数据库中“显示”暴露的属性值.想象一下,您将向测试实体添加测试访问密码属性.使用您的代码,将所有属性的加载完整实体序列化,密码也将被序列化并运行在线上.您不需要更改任何代码来实现,在最坏的情况下,您不会意识到您在http请求中泄露密码.另一方面,当您定义DTO时,如果将此属性显式添加到DTO类,则新实体属性将仅与Json数据序列化.

总结

以上是内存溢出为你收集整理的c# – 为什么我的代码执行懒惰加载,即使我把它关闭在所有可能的点?全部内容,希望文章能够帮你解决c# – 为什么我的代码执行懒惰加载,即使我把它关闭在所有可能的点?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1261949.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-08
下一篇 2022-06-08

发表评论

登录后才能评论

评论列表(0条)

保存