【问题标题】:LINQ to Entities query errorLINQ to Entity 查询错误
【发布时间】:2012-12-10 20:29:26
【问题描述】:

我遇到了一个我不熟悉的错误。我试图谷歌没有成功。 我在出现此错误的地方编写了以下查询。

无法在 LINQ to Entities 查询中构造实体或复杂类型“MyWebProject.Models.UserDetail”。

查询:

UsersContext db = new UsersContext();
        var userdata = (from k in db.UserDetails
                        where k.UserId == WebSecurity.CurrentUserId
                        select new UserDetail()
                        {

                            FullName = k.FullName,
                            Email = k.Email,
                            About = k.About,
                            Link = k.Link,
                            UserSchool = new School()
                            {
                                SchoolId = k.UserSchool.SchoolId,
                                SchoolName = k.UserSchool.SchoolName
                            },
                            UserCourse = new Course()
                            {
                                CourseId=k.UserCourse.CourseId,
                                CourseName=k.UserCourse.CourseName
                            },
                            Country=k.Country
                        }).FirstOrDefault();

类:

public class UserDetail
{
    public int Id { get; set; }
    public int UserId { get; set; }
    public string FullName { get; set; }
    public string Link { get; set; }
    public bool? Verified { get; set; }

    public string Email { get; set; }

    public string About { get; set; }
    public School UserSchool { get; set; }
    public Course UserCourse { get; set; }

    public string Country { get; set; }

}
public class School
{
    public int SchoolId { get; set; }
    public string SchoolName { get; set; }
    public string Country { get; set; }
}
public class Course
{

    public int CourseId { get; set; }
    public string CourseName { get; set; }
    public School School { get; set; }
}

知道出了什么问题吗??

【问题讨论】:

    标签: c# asp.net-mvc linq entity-framework linq-to-entities


    【解决方案1】:

    这似乎是由于您在查询中间创建了复杂属性 School 和 Course 的方式。最好选择用户(删除选择转换),然后使用导航属性来访问这些对象,而不是手动构建它们。只要您使用外键建立适当的关系,导航就是为此而设计的。

    UsersContext db = new UsersContext();
    
    var userdata = (from k in db.UserDetails
        where k.UserId == WebSecurity.CurrentUserId})
        .FirstOrDefault();
    
    // access navigation properties which will perform the joins on your behalf
    // this also provides for lazy loading which would make it more effecient. (it wont load the school object until you need to access it)
    
    userdata.School
    userdata.Course
    

    关于导航属性的 MSDN 文章:http://msdn.microsoft.com/en-us/library/vstudio/bb738520(v=vs.100).aspx

    【讨论】:

    • ok..如果我通过 'userdata' 查看并尝试显示学校名称,如 '@Html.TextBoxFor(m=>m.UserSchool.SchoolName)' 。我不知道学校的名字。
    • 检查 UserDetail 对象以确保它具有正确的 SchoolID 以便它可以链接到学校表。那么那个关联的学校表有名字吗?换句话说,首先确保使用连接进行原始查询会给您预期的结果。验证数据正确后,在控制器渲染视图之前设置一个断点并检查那里的属性。
    • 如果他不使用延迟加载可能是个问题。在下面更新了我的答案,以显示如何显式加载这些对象,而不是依赖延迟加载。
    • @RickB 唯一的问题是,如果他在调用会引发异常的 School 属性之前处理数据库上下文。不过这是个好建议。
    • 如果我在数据库中进行原始查询,例如“select * from userdetails inner join Schools on UserDetails.UserSchool_SchoolId=Schools.SchoolId”,它会给我预期的结果。
    【解决方案2】:

    这应该给你你想要的。它将作为查询的一部分加载您的对象(而不依赖于延迟加载)。

    UsersContext db = new UsersContext();
    var userdata = db.UserDetails.Include(x => x.UserSchool)
                                 .Include(x => x.UserCourse)
                                 .Include(x => x.Country)
                                 .Where(x => x.UserId == WebSecurity.CurrentUserId)
                                 .FirstOrDefault();
    

    【讨论】:

    • 我不知道由于某种原因我不能使用你的代码。它说'错误无法将 lambda 表达式转换为'字符串'类型,因为它不是委托类型'。我还有其他错误吗?
    • @kandroid 尝试将using System.Linq; 添加到您的班级
    • 它已经在那里了。 :) 如果我在数据库中编写一个查询,例如“select * from userdetails inner join Schools on UserDetails.UserSchool_SchoolId=Schools.SchoolId”,它会给我预期的结果。我是代码优先模型的新手。我必须在这里输入任何内容吗: public class UsersContext : DbContext { public UsersContext() : base("DefaultConnection") { } public DbSet UserProfiles { get;放; } 公共 DbSet UserDetails { 获取;放; } }
    【解决方案3】:

    我认为这是因为您的实体与您尝试创建的对象具有相同的名称。尝试重命名要返回的对象。如果您想返回与您的实体相同的类型,请尝试使用 .Include("relationshipname") 功能进行预加载。

    【讨论】:

      【解决方案4】:

      @Yakimych 给出了一个很好的答案。

      您不能(也不应该)投影到映射实体上。但是,您可以投影到匿名类型或 DTO:

      public class ProductDTO
      {
          public string Name { get; set; }
          // Other field you may need from the Product entity
      }
      

      您的方法将返回一个 DTO 列表。

      public List<ProductDTO> GetProducts(int categoryID)
      {
          return (from p in db.Products
                  where p.CategoryID == categoryID
                  select new ProductDTO { Name = p.Name }).ToList();
      }
      

      EF 中的映射实体基本上代表数据库表。如果你投影到一个映射实体上,你基本上做的是部分加载一个实体,这不是一个有效的状态。 EF 不会有任何线索,例如将来处理此类实体的更新(默认行为可能是用空值或对象中的任何内容覆盖未加载的字段)。这将是一个危险的操作,因为您可能会丢失数据库中的一些数据,因此不允许在 EF 中部分加载实体(或投影到映射实体上)。

      更多详情请点击以下链接: The entity cannot be constructed in a LINQ to Entities query

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-04-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多