【问题标题】:LINQ MVC ViewModel: Multiple joins to the same table with optional fieldLINQ MVC ViewModel:使用可选字段多次连接到同一个表
【发布时间】:2013-12-23 11:01:41
【问题描述】:

给定以下数据库结构

类别

身份证 类别名称ResID 父类别(可选)

资源

身份证 文本 朗

并给定一个 ViewModel

public class CategoryViewModel
{
    public int ID { get; set; }
    public int CategoryNameResID { get; set; }
    public string CategoryName { get; set; }

    public int ParentCategory { get; set; }
    public string ParentCategoryName { get; set; }
}

我想获取包含 ParentCategoryName 的所有类别的列表

到目前为止我所做的是:

var categories = (from cat in db.Categories
                  join res in db.Resources on cat.CategoryNameResID equal res.ID
                  select new CategoryViewModel{
ID = cat.ID,
CategoryNameResID = cat.CategoryNameResID,
CategoryName = res.Text,
ParentCategory = cat.ParentCategory,
ParentCategoryName = (from p in db.Resources
where p.ID == cat.ParentCategory
select p.Text)
}).ToList();

我无法弄清楚如何获得 ParentCategoryName 而无需再次迭代,这绝对是错误的。

【问题讨论】:

    标签: c# sql asp.net-mvc linq


    【解决方案1】:

    试试这个:

    (from cat in cats
    join res in resources on cat.ResId equals res.Id let categoryName = res.Text
    join cat1 in cats on cat.ParentId equals cat1.Id into parentJoin
    from pj in parentJoin.DefaultIfEmpty() let parentCatResId =pj==null?0: pj.ResId
    join res1 in resources on parentCatResId equals res1.Id into resJoin
    from res2 in resJoin.DefaultIfEmpty() let parentName = (res2==null?string.Empty:res2.Text)
        select new CategoryVM
        {
            Id = cat.Id,
            ResId = cat.ResId,
            CatName = categoryName,
            ParentId = cat.ParentId,
            ParentName = parentName
        }).ToList();
    

    【讨论】:

    • ParentID不是Resources的外键,我需要的是ParentID的CategoryResId,因为ParentID指的是类别中的ID
    • 是的,除了这种方法只返回 HAVE ParentCategory 的行,我需要的实际上是所有这些
    • 这行得通,但我对语法有点怀疑!
    • LINQ 仅支持 equi join。这是我能找到的实现左连接的唯一方法。
    【解决方案2】:

    假设您的表格中有以下数据

    dbo.Categories
    
    ID  CategoryNameResID   ParentCategory
    1   1                   NULL
    2   2                   NULL
    3   3                   1
    4   4                   NULL
    5   5                   4
    6   6                   4
    7   7                   4
    
    
    dbo.Resources
    
    ID  Text                Lang
    1   Standard            en-GB
    2   Custom              en-GB
    3   Standard Oversize   en-GB
    4   Loose               en-GB
    5   Loose 2F Set        en-GB
    6   Loose (4” Scale)    en-GB
    7   Loose (6” Scale)    en-GB
    

    以下 LINQ 语句将输出所需的结果:

    public class CategoryViewModel
    {
        public int ID { get; set; }
        public int CategoryNameResID { get; set; }
        public string CategoryName { get; set; }
    
        public int? ParentCategory { get; set; }
        public string ParentCategoryName { get; set; }
    }   
    
    
    var categories = (from cat in Categories
                      join res in Resources on cat.CategoryNameResID equals res.ID let categoryName = res.Text
                      select new CategoryViewModel
                      {
                        ID = cat.ID,
                        CategoryNameResID = cat.CategoryNameResID,
                        CategoryName = categoryName,
                        ParentCategory = cat.ParentCategory,    
                        ParentCategoryName = Resources.FirstOrDefault(r => r.ID == cat.ParentCategory).Text
                      }).ToList();
    
    
    foreach(var c in categories)
    {
       Console.WriteLine(c.CategoryName + " - " + c.ParentCategoryName);   
    }
    
    // Prints
    Standard - 
    Custom - 
    Standard Oversize - Standard
    Loose - 
    Loose 2F Set - Loose
    Loose (4” Scale) - Loose
    Loose (6” Scale) - Loose
    

    【讨论】:

    • An exception of type 'System.NotSupportedException' occurred in mscorlib.dll but was not handled in user code Additional information: The methods 'Single' and 'SingleOrDefault' can only be used as a final query operation. Consider using the method 'FirstOrDefault' in this instance instead.
    • 更新了使用 FirstOrDefault() 的答案
    • 您没有从父类别中获取 CategoryNameResID,因此您无法在 Resources 表中匹配它...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-26
    • 2021-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多