2010-12-16 84 views
0

我有几个只共享少数导航属性和ID的表。 我想每个具体类型继承表将是有趣在这里.. 它看起来是这样的:实体框架:每个具体类型的表和表中的唯一ID

联系(基地,抽象的,没有映射)
- 使用ContactID
- 导航属性与其他表((?)电子邮件,电话,..)

人:联系(映射到表人用各种属性+的ContactID)
- 各种属性

公司:联系(映射到表W公司ith各种属性+联系人ID)
- 各种属性

现在为了这个工作,主键(contactID)应该在所有表中都是唯一的。 2选项然后:
- GUID(不是粉丝)
- 附加的数据库表生成标识(只有一个ContactID字段,派生表具有FK),这将不会在EF中映射。

此设置是否可行? 另外,ObjectContext中会发生什么? EF在调用SaveChanges之前生成什么样的临时密钥?它是唯一的跨物体吗?

感谢您的任何想法。 麦克风。

回答

1

我们使用一个类似的建筑与如下因素DB设计:

ContactEntity

  • ID

ContactPossibility

  • ID
  • 位置
  • ContactTypeID
  • ContactEntityID

地址

  • ID(= PK和FK到ContactPossibility.ID)

电话

  • ID(= PK和FK到ContactPossibility.ID)

  • ID(= PK和FK到ContactEntity.ID)

公司

  • ID(= PK和FK到ContactEntity.ID)
  • 名称

这导致两个抽象类实体模型:ContactEntity(CE)& ContactPossibility(CP)和多个派生类(地址= CP,电子邮件= CP,人= CE,Company = CE)。抽象类和派生类(db中的行)共享相同的唯一标识符,因为我们在派生类中使用ID字段,这是抽象类主键的外键。我们使用Guid's,因为我们的软件需要离线工作(不连接到主数据库),我们必须平稳处理同步问题。另外,Guid的问题是什么?

实体框架确实支持这个db/class设计非常好,我们从这个设计中获得很多乐趣。

该设置是否可行? 另外,ObjectContext中会发生什么? EF在调用SaveChanges之前会生成什么样的临时密钥? 它是唯一的对象?

建议的设置非常非常可行! ObjectContext的行为良好,并将毫不费力地插入,更新和删除派生类的正确表。临时密钥?如果您对抽象类的主键和外键的派生类使用ID的模式,则不需要它们。而Guid的你可以很确定这是独一无二的objetcs。

此外:从CP到CE的外键将为每个CE(人员,公司,用户等)提供可跟踪的联系可能性集合。这是真正的酷和方便。

希望这有助于...

+0

非常感谢,这正是设计的我试图达到的那种。我有一个类似的“CP '表作为一个多对多的表,另外一个问题(实际上是一个复合的问题):你是否将基类(CP,CE)映射到它们的基础表?如果你这样做,我想我们是TPT设置(不是TPC)还是我错了?如果是TPT,它不会产生令人讨厌的SQL与很多工会?谢谢。 – Mike 2010-12-16 17:03:41

+0

(更新为我的最后一个问题:我想这就是你的'ContactTypeID'在CP作为你的基类中的一个鉴别器?所以你不必整合所有的联系表来找出类型,对吧?) – Mike 2010-12-16 17:44:38

+0

Hi Mike,C P表充当多对多的表......在我的情况下,这对许多(CP)都是1(CE)。是的,我将(抽象)基类映射到它们的基础表,实际上EntityModel生成器会为我做这件事;)是的,这是一个Table-Per-Type场景。这种情况也提供了一些数据库优化,因为您必须跟踪更少的外键,并且使用其他CP或CE“类型”更容易维护和扩展。 – 2010-12-16 19:31:52

1

(在评论部分没有足够的空间)

我一直在运行一些测试。
只要您只指定您要查询的子类型(例如,您的案例中的“地址”),就可以。
但是,如果您查询基本类型(即使您不需要子类型信息),例如。只有ContactPossibility.ID,生成的SQL将UNION所有子类型表。
因此,查询“可跟踪”联系可能性集合可能会产生性能问题。

我试图解决这个问题,通过解开基本实体并将继承的实体拆分到它们自己的表+公共表中,基本上将TPT转换为TPC:从概念角度来看,这工作得很好(经过大量edmx编辑)。
直到我意识到这是愚蠢的... :)事实上,在这种情况下,你将永远需要联盟所有基础表来查询常见数据...
(虽然我不确定在最后描述的情况下这个帖子,没有追求测试它)

所以我想,因为主要是我需要查询特定类型(人,公司,地址,电话,..),现在会好起来的并希望MS会在EF4.5中修复。

所以我得查询时要小心,另一个有趣的例子:
比方说,你要选择一个人,然后查询自己的地址,像(试图按照您的命名):
var person = from b in context.ContactEntities.OfType-Person-() where b.FirstName.StartsWith("X") select b;
var address = from a in context.ContactPossibilities.OfType-Address-() where **a.ContactEntity == person.FirstOrDefault()** select a;
这将产生接触所得到实体的所有表和性能问题之间的联盟:生成的SQL需要ContactPossibility表,并加入到ContactPossibilityID地址,然后加入全部联系派生表的联合加入了与基地联系表,最终加入过滤后的Pers桌上。

然而,考虑以下选择:
var person = from b in context.ContactEntities.OfType-Person-() where b.FirstName.StartsWith("X")<BR> select b;
var address = from a in context.ContactPossibilities.OfType-Address-() where **a.ContactID == person.FirstOrDefault().ID** select a;
这将很好地工作:生成的SQL需要ContactPossibility表,并加入到ContactPossibilityID地址,然后加入过滤Person表。

Mike。

+0

请注意,以下替代相同的查询也工作正常:var address = from d in context.Contactpossibilities.OfType

() 在上下文中加入e.Contacts.OfType ()on d.ContactID等于e.ContactID select d; – Mike 2010-12-20 14:33:26

0

干得好Mike!我会理解这种情况。当然,希望MS能以更优雅的方式来做事。而关于查询,我总是应该根据外键进行比较!

只好给它一个答案,因为没有足够的声誉编辑您的答案:(

相关问题