我正在尝试首先使用实体框架代码为c#.net Core应用程序开发数据模型。
我基本上拥有的是下面的数据模型。
有表Dog
和Person
。它们各自包含不同的信息。例如,我可以有不同类型的狗。人可以有一些特定的东西,而不适用于狗。
Person
和Item
之间存在1:1关系。 Dog
和Item
之间存在相同的关系。
除该表ItemReference
之外,还包含项之间的子母关系。例如,狗与人之间存在儿童-父母关系(狗主人-狗或人可能是兄弟姐妹)
我需要按字母顺序列出狗和人的清单(将它们混合在一起)。此外,我需要能够进入以下每个详细信息页面。
使用这种方法确实很愚蠢,因为将来可能会有更多的表。例如Cat
或Car
,则每次都需要重新编写这些If语句。
@foreach (var x in Model.Item.OrderBy(y=>y.ItemName))
{
if (x.ItenType == "Dog")
{
<li><a asp-page="DogDetails" asp-route-id="@x.Item.Dog.Id">@x.ItemName</a></li>
}
if (x.ItenType == "Person")
{
<li><a asp-page="PersonDetails" asp-route-id="@x.Item.Person.Id">@x.ItemName</a></li>
}
}
任何人都知道如何制作这样的数据模型,从而使其设计更智能吗?
任何帮助表示赞赏
表Dog
,Person
和Item
如下所示:
狗
Id DogName DogTypeId DogStatusId ItemId
1 "Alex" 1 1 1
2 "Rex" 2 1 2
人
Id PersonName PersonStatusId ItemId
1 "Joe" 1 3
2 "Jane" 2 4
项目
Id ObjectName ItemType
1 "Alex" "Dog"
2 "Rex" "Dog"
3 "Joe" "Person"
4 "Jane" "Person"
答案 0 :(得分:2)
您的对象图并不完全清楚。看来Dog
和Person
与Item
相关,但是根据您的描述和简短的代码示例,它们似乎实际上是类型的项目。如果是这样,您应该采用继承策略,而不是合成。
public class Item
public class Dog : Item
public class Person : Item
默认情况下,EF将使用TPH(每个层次的表)策略处理继承,这在这里似乎不合适。相反,我认为您将需要TPT(每种类型的表),可以通过在派生类上使用Table
属性来实现:
[Table("Dogs")]
public class Dog : Item
[Table("Persons")]
public class Person :
这将创建三个表Dogs
,Persons
和Items
。所有项目共有的任何数据,无论是狗还是人,显然都将进入您的Item
类,并将最终出现在Items
表中。外键将被添加到指向Dogs
表的Persons
和Items
表上。例如,当您检索Dog
时,EF将自动加入Items
中的相应记录以创建完整的Dog
。
这将为您的查询提供一些特殊功能。当然,您可以使用_context.Items
来获取所有项,无论类型如何,但是您也可以将DbSet
和Dog
分别使用Person
来查询那些独立的:例如_context.Dogs
。即使没有显式的DbSet
,也可以使用通用的Set<TEntity>
方法:_context.Set<Dog>()
。此外,您可以使用OfType<TEntity>
来过滤Items
集_context.Items.OfType<Dog>()
。
最后,即使您仅检索Items
,EF仍会跟踪每个Item
的最终类型,这意味着您可以执行模式匹配之类的事情:
if (item is Dog dog)
{
// `dog` is now a variable in this scope of your `item` downcast to `Dog`
}
或在switch语句中:
switch (item)
{
case Dog dog:
// do something with `dog`
break;
case Person person:
// do something `person`
break;
default:
// do something with generic items (`item`)
break;
}
编辑
我意识到我只提到了以下内容,而没有明确说明。由于Dog
和Person
在TPT中是完全不同的表,因此您可以在其中定义完全独立的关系。例如,Dog
可以与DogStatus
有关系,而不会影响Person
发生的任何事情。从技术上来说,即使使用TPH,您仍然可以执行此操作,但最终会在Items
表上产生一堆可为空的外键,这将是一团糟,并且会破坏规范化。