我有一个多对多关系表,试图在表中显示报告列表。
我的桌子看起来像这样:
报告表:
Id| ReportName |
1 | report 1 |
2 | report 2 |
3 | report 3 |
报告类别表:
Id| Name |
1 | General |
2 | Specific |
ReportMapping连接表:
Id| ReportId | CategoryId |
1 | 1 | 1 |
2 | 1 | 2 |
3 | 2 | 1 |
4 | 2 | 2 |
在此示例中,报告可以有多个类别,只有2个,但可以有更多类似的例子,比如说1个报告可以有5个类别,例如General,Specific,Test2,Test3和Test4
我想在.net核心应用程序的表/列表上显示以下格式:
ReportId| Report Name | Report Categories
1 | report 1 | General, Specific
2 | report 2 | General, Specific
我很难使它在sql服务器和EF核心linq中都可以工作。关于如何开始的任何指示?到目前为止,我已经能够将表格连接在一起,但是不知道如何将结果串联到具有多个类别的报表的一行中。我得到的是类似下面的内容,而不是上面的示例所希望的结果:
ReportId | Report Name | Report Categories
1 | report 1 | General
1 | report 1 | Specific
2 | report 2 | General
2 | report 2 | Specific
任何帮助将不胜感激,谢谢!
答案 0 :(得分:2)
您描述的模型与EF Core文档中Many-to-many示例中的Post
/ Tag
模型几乎相同。
所以您将有3个代表表格记录的类
public class Report
{
public int Id { get; set; }
public string ReportName { get; set; }
public ICollection<ReportMapping> Mappings { get; set; } // navigation
}
public class ReportCategory
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<ReportMapping> Mappings { get; set; } // navigation
}
public class ReportMapping
{
public int Id { get; set; }
public int ReportId { get; set; }
public int CategoryId { get; set; }
public Report Report { get; set; } // navigation
public ReportCategory Category { get; set; } // navigation
}
和3个DbSet
代表您的表:
public DbSet<Report> Reports { get; set; }
public DbSet<ReportCategory> ReportCategories { get; set; }
public DbSet<ReportMapping> ReportMappings { get; set; }
请注意,联结实体(表)中的Id
属性(列)是多余的,因此,如果您不受现有数据库的约束,请考虑删除它并像示例中那样配置复合PK
modelBuilder.Entity<ReportMapping>()
.HasKey(e => new { e.ReportId, e.CategoryId });
还要注意标记为// navigation
的属性。这些就是所谓的导航属性(请参见Definition of Terms),它们表示关系的末端,并允许您访问LINQ查询中的相关数据。
无需使用join
构造-请参见Don’t use Linq’s Join. Navigate!,这是EF(核心)推荐/首选的LINQ查询编写方式。
这是您的数据库模型。由于您希望查询返回特定的结果类型,因此首先定义一个代表该结果的类(例如DTO,ViewModel等),例如:
public class ReportInfo
{
public int ReportId { get; set; }
public string ReportName { get; set; }
public IEnumerable<string> ReportCategories { get; set; }
}
请注意,我将ReportCategories
定义为字符串序列,而不是单个字符串。这是因为第一,数据库本身不支持结果集的字符串连接,其次,第二,用逗号连接只是表示数据的多种方式之一。通常,数据格式化是客户的责任。因此,您以原始数据的原始格式(字符串列表)返回数据,并让客户端将其格式化(在这种情况下,可以使用string.Join(",", info.ReportCategories)
轻松地做到这一点)。
最后是实际查询。有了导航属性,它就非常简单-基本上只需Select
s:
var result = db.Reports
.Select(r => new ReportInfo
{
ReportId = r.Id,
ReportName = r.ReportName,
ReportCategories = r.Mappings
.Select(m => m.Category.Name)
.ToList() // <-- to avoid N + 1 subquery in EF Core 2.1+
})
.ToList();