【问题标题】:LINQ To Entity - Inner Join issueLINQ To Entity - 内部连接问题
【发布时间】:2022-01-14 17:09:58
【问题描述】:

我有两个相关的表格,如下所示:

用户:

public partial class Users
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Users()
    {

    }

    public int ID { get; set; }
    public int UserType_ID { get; set; }
    public string Email { get; set; }

    public virtual UserTypes UserTypes { get; set; }
}

用户类型:

public partial class UserTypes
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public UserTypes()
    {
        this.Users = new HashSet<Users>();
    }

    public int ID { get; set; }
    public string Name { get; set; }
    public string Title { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<Users> Users { get; set; }
}

对于 UserType 的访问名称,我将此 linq 写入实体:

string[] UserTypes = new string[1];

using (Crypto_Entities entities = new Crypto_Entities())
{
    int User_ID_Integer = int.Parse(User_ID.Trim());

    var user = (from User in entities.Users
                //join UserType in entities.UserTypes on User.UserType_ID equals UserType.ID
                where User.ID == User_ID_Integer
                select User).FirstOrDefault();
    if (user != null)
    {
        UserTypes[0] = user.UserTypes.Name;
    }
}

我的问题是为什么user.Name 对我的目的不起作用,join 在 linq to entity 中的好处是什么?
如果我像在查询中那样删除join,我仍然可以看到带有user.UserTypes.Name 的UserType 的名称字段。

【问题讨论】:

    标签: c# asp.net entity-framework linq inner-join


    【解决方案1】:

    如果您已正确定义导航属性,则不需要加入。如果您只需要Name,请不要检索完整的实体。

    string[] UserTypes = new string[1];
    
    using (Crypto_Entities entities = new Crypto_Entities())
    {
        int User_ID_Integer = int.Parse(User_ID.Trim());
    
        var query = 
            from User in entities.Users
            where User.ID == User_ID_Integer
            select User.UserTypes.Name;
    
        var name = query.FirstOrDefault();
        if (name != null)
        {
            UserTypes[0] = name;
        }
    }
    

    如果您在查询中使用导航属性,EF 会自动生成所有需要的连接。但是,如果您只选择整个实体而不定义 Include - EF 将不会加载相关数据。这是有道理的,否则如果有很多关系,您可能会加载几乎整个数据库。

    【讨论】:

    • 感谢您的回答。如果我取消注释加入,为什么 user.Name 不起作用?
    • 也可以代替FirstOrDefault,只填充数组UserTypes = query.ToArray();
    • 我对你的代码有这个错误:An expression of type 'UserTypes' is not allowed in a subsequent from clause in a query expression with source type 'DbSet&lt;Users&gt;'. Type inference failed in the call to 'SelectMany'.
    • 我已经更正了答案。错过了 UserTypes 只是实体。
    【解决方案2】:

    由于您已经在实体中设置了关系,因此您无需手动将 join 写入 load related data

    var user = entities.Users
       .Include(u => u.UserTypes)
       .Where(u => u.ID == User_ID_Integer)
       .FirstOrDefault();
    

    至于您的联接无用 - EF Core 将代码转换为实际 SQL(您可以check),并且由于您没有从联接表中选择任何数据 - 它与 SQL 查询一样无用您仅从一个连接结果表中选择了字段。

    【讨论】:

    • 感谢您的回答,如果我取消注释加入,为什么 user.Name 不起作用?
    • @SilverLight 正如我在回答中所写的那样 - 因为user.UserTypes.Name 没有从数据库中返回,所以您只需执行联接而不从第二个表中选择任何数据(即select t1.* from table1 t1 join table2 t2 on.... 之类的东西)。您可以执行select new{User, UserTypes}).FirstOrDefault().User.UserTypes.Name 之类的操作,它应该可以工作。
    • 谢谢,我对你的代码有这个错误:Cannot convert lambda expression to type 'string' because it is not a delegate type
    • @SilverLight 究竟是什么代码?你能发布完整的sn-p吗?
    • 您的答案中的代码 - 不是注释。
    猜你喜欢
    • 2011-06-26
    • 1970-01-01
    • 1970-01-01
    • 2011-12-07
    • 1970-01-01
    • 2016-04-17
    • 1970-01-01
    • 2013-05-24
    • 2011-01-13
    相关资源
    最近更新 更多