将多个表与实体框架代码中的单个通用表相关联 [英] Relate Multiple Tables to Single General Purpose Table in Entity Framework Code First
问题描述
public class MyString
{
public Guid Id {得到;组; }
public string Value {get;组; }
}
public class MyEntity
{
public Guid Id {get;组; }
public virtual List< MyString> {get;组; }
}
public class MyOtherString
{
public Guid Id {get;组; }
public string Value {get;组; }
}
public class MyOtherEntity
{
public Guid Id {get;组; }
public virtual List< MyOtherString> {get;组; }
}
我真的想结合 MyString
和 MyOtherString
成一个实体:
public class GeneralPurposeString
{
public Guid Id {get;组; }
public string Value {get;组; }
}
public class MyEntity
{
public Guid Id {get;组; }
public virtual List< GeneralPurposeString> {get;组; }
}
public class MyOtherEntity
{
public Guid Id {get;组; }
public virtual List< GeneralPurposeString> {get;组; }
}
除了现在我要在<$包含 GeneralPurposeString
的每个实体的c $ c> GeneralPurposeString 。
我想要的方法是在 GeneralPurposeString
表(但不是实体)上指定该项目所属的实体的另一个父类别列。我使用 Guid
为主键,所以表可能看起来像这样:
CREATE TABLE [GeneralPurposeString]
(
[Id] uniqueidentifier NOT NULL
CONSTRAINT PK_GeneralPurposeString PRIMARY KEY,
[ParentEntityCategory] uniqueidentifier NOT NULL,
[ParentEntityId] uniqueidentifier NOT NULL,
[Value] nvarchar(MAX)
)
一些如何在Code First中指定 MyEntity
有一个特定的类别,而且它的集合 GeneralPurposeString
使用该类别,和 MyOtherEntity
使用另一个类别(Guid)为 GeneralPurposeString
的集合。
关键是 GeneralPurposeString
可以是任何其他实体的集合,加载父实体并包含集合将自动加载而不必明确指定的类别。
所有这些的目的是
- 允许.NET代码拥有
GeneralPurposeString
无法复制的代码(实际实用程序或业务逻辑代码)。这可能还可以通过继承和显式映射来实现,但仍然会在数据库中留下多个表(参见#2)。 - 数据库中只有一个表
GeneralPurposeString
。这更是一个整洁的问题。性能可能会更好与多个表,但索引在ParentEntityCategory
/ParentEntityId
并覆盖值
应该是查询的良好性能。 - 不必显式地对这种关系进行编码,并且需要在任何地方查找。
我在想,如果我可以超越#2,并在幕后使用一个单独的表,并实现一个派生类,那么将是最简单的路线。
所以只是:
public class GeneralPurposeString
{
public Guid Id {get;组; }
public string Value {get;组; }
}
//这只是一个泛型的MyEntity会员引脚的一个GeneralPurposeString
public class MyEntityString:GeneralPurposeString {}
public class MyEntity
{
public Guid Id {get;组; }
public virtual List&MyEntityString>字符串{get;组;
}
// Cool GeneralPurposeStrings属于MyOtherEntity
public class MyOtherEntityString:GeneralPurposeString {}
public class MyOtherEntity
{
public Guid Id {get;组; }
public virtual List< MyOtherEntityString>字符串{get;组; }
}
public class MyContext:DbContext
{
public DbSet< MyEntity>新新旗新新旗新新旗旗新新旗旗新新旗人1992:组; }
public DbSet< MyOtherEntity> MyOtherEntities {get;组;
}
我不必将派生类添加到 DbContext
,默认情况下,这些表命名为派生类的复数,所以实际上很简单。
我以前的即使EF支持,父母类别的思路也需要额外的编码/注释。这使用纯粹的惯例,在注释或 OnModelCreating()
中
我没有看到任何在这个时间点额外的桌子伤害。我没有看到需要(目前)将一个表中的所有数据都用于报告,但这真的取决于通用实体的类型,所以我可能需要在将来重新访问,或者我可能会采取如果我需要一个表格中的数据,那么多对多路由。
我还可以:
公共静态类GeneralPurposeStringExtensions
{
public static void SassThatHoopyFrood(this GeneralPurposeString s)
{
// do stuff
}
}
Many times I have a general purpose entity that other entities contain a collection of. I don't want to have a new collection entity for each parent entity type that needs it but would like to re-use a single general purpose entity. For performance reasons, I also don't want to explicitly define many-to-many relationships as in this answer. The simplest example would be a collection of strings.
public class MyString
{
public Guid Id { get; set; }
public string Value { get; set; }
}
public class MyEntity
{
public Guid Id { get; set; }
public virtual List<MyString> { get; set; }
}
public class MyOtherString
{
public Guid Id { get; set; }
public string Value { get; set; }
}
public class MyOtherEntity
{
public Guid Id { get; set; }
public virtual List<MyOtherString> { get; set; }
}
I'd really like to combine MyString
and MyOtherString
into a single entity:
public class GeneralPurposeString
{
public Guid Id { get; set; }
public string Value { get; set; }
}
public class MyEntity
{
public Guid Id { get; set; }
public virtual List<GeneralPurposeString> { get; set; }
}
public class MyOtherEntity
{
public Guid Id { get; set; }
public virtual List<GeneralPurposeString> { get; set; }
}
Except now I'm going to have an additional foreign key in GeneralPurposeString
for every entity that contains a collection of GeneralPurposeString
.
What I would like would be a way to have an additional parent category column on the GeneralPurposeString
table (but not the entity) that would specify which entity the item belongs to. I use Guid
for primary keys, so the tables could look something like this:
CREATE TABLE [GeneralPurposeString]
(
[Id] uniqueidentifier NOT NULL
CONSTRAINT PK_GeneralPurposeString PRIMARY KEY,
[ParentEntityCategory] uniqueidentifier NOT NULL,
[ParentEntityId] uniqueidentifier NOT NULL,
[Value] nvarchar(MAX)
)
And some how in Code First to specify that MyEntity
has a certain category, and that it's collection of GeneralPurposeString
uses that category, and MyOtherEntity
uses another category (Guid) for it's collections of GeneralPurposeString
.
The key would be that GeneralPurposeString
could be a collection in any other entity and that loading the parent entity and including the collection would automatically load without having to explicitly specify the category.
The purposes for all of this are
- Allow .NET code to have
GeneralPurposeString
code that wasn't replicated everywhere (actual utility or business logic code). This can probably also be accomplished through inheritance and explicit mapping but that would still leave multiple tables in the database (see #2). - Have only one table in the database for
GeneralPurposeString
. This is more of a tidiness issue. Performance would possibly be better with multiple tables, but indexing onParentEntityCategory
/ParentEntityId
and coveringValue
should be good performance for lookups. - Not have to explicitly code this relationship and the lookups everywhere it's needed.
I'm thinking if I can get over #2 and be OK with a separate table behind the scenes and implementing a derived class, that will be the simplest route to go.
So just:
public class GeneralPurposeString
{
public Guid Id { get; set; }
public string Value { get; set; }
}
// It's just a GeneralPurposeString with a fancy MyEntity membership pin
public class MyEntityString: GeneralPurposeString {}
public class MyEntity
{
public Guid Id { get; set; }
public virtual List<MyEntityString> Strings { get; set; }
}
// Cool GeneralPurposeStrings belong to MyOtherEntity
public class MyOtherEntityString: GeneralPurposeString {}
public class MyOtherEntity
{
public Guid Id { get; set; }
public virtual List<MyOtherEntityString> Strings { get; set; }
}
public class MyContext: DbContext
{
public DbSet<MyEntity> MyEntities { get; set; }
public DbSet<MyOtherEntity> MyOtherEntities { get; set; }
}
I don't have to add the derived classes to the DbContext
and the tables get named with the plural of the derived class by default, so it's actually pretty straight forward.
My previous train of thought with the Parent Category would require additional coding/annotation even if EF supported it. This uses purely convention and nothing extra needed in annotations or in OnModelCreating()
.
I'm not seeing any harm in extra tables at this point in time. I don't see a need (currently) to have all of the data in one table for reporting, but that really depends on the type of general purpose entity, so I may need to revisit this in the future, or I may just take the many-to-many route if I do need the data in one table.
And I can still have:
public static class GeneralPurposeStringExtensions
{
public static void SassThatHoopyFrood(this GeneralPurposeString s)
{
// do stuff
}
}
这篇关于将多个表与实体框架代码中的单个通用表相关联的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!