Linq 一对多表关系的实体拆分
在本文()之后,我将所有数据库表分为两部分:第一个表只包含与语言无关的数据(主键等),第二个表包含每种语言一条记录,其中包含本地化数据和该语言的ISO代码。这两个表之间的关系是一对多。 下面是数据模型的屏幕截图: 因为网站有8种语言,所以对于表“CourseCategory”中的每条记录,我在表“CourseCategoryContents”中有8条记录。“课程”和“课程内容”也是如此 然后我使用实体拆分,以便课程类别只有一个实体,课程只有一个实体:Linq 一对多表关系的实体拆分,linq,entity-framework,split,entity,multilingual,Linq,Entity Framework,Split,Entity,Multilingual,在本文()之后,我将所有数据库表分为两部分:第一个表只包含与语言无关的数据(主键等),第二个表包含每种语言一条记录,其中包含本地化数据和该语言的ISO代码。这两个表之间的关系是一对多。 下面是数据模型的屏幕截图: 因为网站有8种语言,所以对于表“CourseCategory”中的每条记录,我在表“CourseCategoryContents”中有8条记录。“课程”和“课程内容”也是如此 然后我使用实体拆分,以便课程类别只有一个实体,课程只有一个实体: public class CourseCat
public class CourseCategoryConfiguration : EntityTypeConfiguration<WebCourseCategory>
{
public CourseCategoryConfiguration()
{
Map(m =>
{
m.Properties(i => new { i.Id, i.Order, i.Online });
m.ToTable("CourseCategories");
});
Map(m =>
{
m.Properties(i => new { i.LanguageCode, i.Name, i.Permalink, i.Text, i.MetaTitle, i.MetaDescription, i.MetaKeywords });
m.ToTable("CourseCategoryContents");
});
}
}
public class CourseConfiguration : EntityTypeConfiguration<WebCourse>
{
public CourseConfiguration()
{
Map(m =>
{
m.Properties(i => new { i.Id, i.CategoryId, i.Order, i.Label, i.ThumbnailUrl, i.HeaderImageUrl });
m.ToTable("Courses");
});
Map(m =>
{
m.Properties(i => new { i.LanguageCode, i.Name, i.Permalink, i.Text, i.MetaTitle, i.MetaDescription, i.MetaKeywords, i.Online });
m.ToTable("CourseContents");
});
}
}
实体拆分可以很好地处理一对一关系,但这里我有一对多关系
该网站有3种语言(“英语”、“德语”、“法语”)的内容(课程类别和课程)。
EF以正确的语言(如英语)正确返回所有课程及其类别,但每个记录返回3次。这是因为我也有3种语言的课程分类
我提出的唯一可行的解决方案是避免使用“.Include(Category)”,首先获取所需语言的所有课程,然后在foreach循环中,为每门课程检索其语言类别。我不喜欢这种惰性加载方法,我希望一次检索所有需要的数据
谢谢 恐怕没有解决所有问题的办法,每种方法都会有妥协 我在相当大的项目中使用了数据库方法(10+语言相关的表)和资源文件方法,前提是数据是静态的并且没有变化(即您不收取不同的价格或其他任何费用)我一定会考虑从数据库模型中提取抽象语言,并使用资源键,然后从文件加载数据。 原因或这是您目前遇到的无法过滤包含项的问题(这可能在EF6中有所改变?我知道这在要做的事情列表中)。您可能可以将其读入内存并进行过滤,尽管这与您的做法类似,但这意味着它对我们来说性能不是很好,我必须编写存储过程,我刚刚通过iso语言并在EF中执行 从维护的角度来看,这也更容易,对于DB项目,我必须编写一个管理控制台,以便人们可以登录并编辑不同语言的值等。使用资源文件,我只是将值复制粘贴到excel中,并通过电子邮件发送给我们用来翻译的人 这取决于你的项目的复杂性和你喜欢什么,我仍然会考虑这两种方法。p> TLDR:我发现的选项有: 1) 内存中的过滤器 2) 带过滤器的延迟加载 3) 将存储过程写入EF并映射该结果 4) 改用资源 希望这有帮助
编辑:查看图表后,您可能需要根据语言相关值进行搜索?在这种情况下,资源可能不起作用。如果您只是让他们从菜单中导航,那么您就可以开始了。最好的解决方案是将表格映射到模型,因为在模型
课程中,
类将具有导航属性ICollection
在这种情况下,您只需“根据您的应用程序设计”将此模型投影到DTO或ViewModel
e、 g。
你的模型会像这样
public class Course
{
public int Id {get; set;}
public int Order {get; set;}
public ICollection<CourseCategoryContent> CourseCategoryContents {get; set;}
}
public class CourseCategoryContent
{
public string LanguageId {get; set;}
public string Name {get; set;}
}
最后做投影
public IQueryable<CourseDTO> GetCourseDTOQuery ()
{
return dbContext.Courses.Select(x=>new CourseDTO{
Id = x.Id,
Order = x.Order,
Name = x.CourseCategoryContents.FirstOrDefault(lang => lang.LanguageId == lang).Name,
});
}
public IQueryable GetCourseDTOQuery()
{
返回dbContext.Courses.Select(x=>newcoursedto{
Id=x.Id,
订单=x.订单,
Name=x.CourseCategoryContents.FirstOrDefault(lang=>lang.LanguageId==lang).Name,
});
}
请注意,返回类型是IQueryable,因此您可以在访问数据库之前对其执行任何筛选、排序或分组操作
希望这有帮助
public class CourseDTO
{
public int Id {get; set;}
public int Order {get; set;}
public string Name {get; set;}
}
public IQueryable<CourseDTO> GetCourseDTOQuery ()
{
return dbContext.Courses.Select(x=>new CourseDTO{
Id = x.Id,
Order = x.Order,
Name = x.CourseCategoryContents.FirstOrDefault(lang => lang.LanguageId == lang).Name,
});
}