实体框架与过滤器关联
我的模型中有以下模型:
Patient
Vendor
Organization
每个实体都需要地址。
地址基本上如下所示,
Address
AddressTypeId // with Navigation Property/Association to AddressType
EntityKey // indicates the PK Id of the entity this address is for
AddressType
EntityId // indicates the entity type this address type corresponds to (Patient or Vendor)
// This should be on the AddressType, not the Address, since we need a way of knowing what kind of AddressTypes are available to create for new addresses for Patients, Vendors, and Organizations
//...that is Patients support AddressType X, Vendors support AddressType Y, etc.
我想在地址的 EntityKey 属性上创建患者、供应商和组织的关联 - 每个关联都有一个过滤器约束,即地址的 AddressType.EntityId 是该实体的匹配 EntityId(1 表示患者, 2 代表供应商,3 代表地址)。
这样做的最佳方法是什么?市场上的大多数 ORM 都支持这种情况……而且这肯定是一种非常常见的情况。
注意:我不想创建 PatientAddress/PatientAddressType、VendorAddress/VendorAddressType 和 OrganizationAddress/OrganizationAddress 类型派生实体。它严重扰乱了模型并使其基本上难以理解。
现在,我正在通过在 LINQ 查询中执行显式联接来解决这个问题:
const int patientTypeEntityId = 1;
var query = from p in repository.Patients
let addresses = repository.Addresses.Where(a =>
a.EntityKey == p.Id & a.AddressType.EntityId == patientTypeEntityId)
select new { Patient = p, Addresses = a }
但我不想继续这样做。
I have the following model in my model:
Patient
Vendor
Organization
each of these entities needs Addresses.
The Address basically looks like the following
Address
AddressTypeId // with Navigation Property/Association to AddressType
EntityKey // indicates the PK Id of the entity this address is for
AddressType
EntityId // indicates the entity type this address type corresponds to (Patient or Vendor)
// This should be on the AddressType, not the Address, since we need a way of knowing what kind of AddressTypes are available to create for new addresses for Patients, Vendors, and Organizations
//...that is Patients support AddressType X, Vendors support AddressType Y, etc.
I want to create an association for Patient, Vendor, and Organization on the EntityKey property on Address - each with a filter constraint that the Address's AddressType.EntityId is the matching EntityId for that entity (1 for Patient, 2 for Vendor, 3 for Address).
What is the best way of doing this? Most ORM's on the market support this kind of scenario....and it's certainly a very common one.
NOTE: I don't want to create PatientAddress/PatientAddressType, VendorAddress/VendorAddressType, and OrganizationAddress/OrganizationAddress type derived entities. It severely clutters the model and makes it basically incomprehensible.
Right now I'm solving this by doing explicit joins in my LINQ queries:
const int patientTypeEntityId = 1;
var query = from p in repository.Patients
let addresses = repository.Addresses.Where(a =>
a.EntityKey == p.Id & a.AddressType.EntityId == patientTypeEntityId)
select new { Patient = p, Addresses = a }
but I don't want to continue having to do this.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果我理解正确的话,您希望在您的
Patient
、Vendor
等中拥有一个地址集合......并以某种方式告诉 EF
Patient.Addresses< /code> 仅填充地址类型为“Patient”的地址。
我认为这是不可能的,原因如下:
如果您没有在
Address
中公开外键(那里没有EntityKey
属性),您必须告诉 EF在映射中键入密钥(否则它将创建/假设两个不同的 FK 列):由于两个不同关系的重复“EntityKey”列,这会引发异常。
接下来我们可以尝试的是将外键公开为
Address
中的属性(EntityKey
属性在那里),然后使用此映射:: (令人惊讶的是)不会抛出异常,而是在数据库中的
Patient
-Address
和Vendor
-Address< 之间创建两个 FK 约束/code> 具有相同的 FK 列
EntityKey
。对于您的模型,我认为这没有意义,因为它要求始终存在具有相同 PK 的Patient
和Vendor
如果您的地址包含一些EntityKey
。因此,您必须手动删除数据库中的这些 FK 约束(这对我来说感觉非常 hacky)。最后一件事是,您无法为导航属性的延迟加载和急切加载指定过滤器。
Addresses
集合将始终填充与Patient
或Vendor
的 PK 具有相同EntityKey
的地址分别。您可以通过显式加载来应用过滤器:但是您必须确保永远不会对
Addresses
集合使用延迟加载或急切加载。所以,这并不是真正的解决方案,我们应该立即忘记它。对我来说最丑陋的一点是你不能对 EntityKey 进行 FK 约束。换句话说:数据库允许 EntityKey = 1,而没有引用该 PK 的
Patient
或Vendor
(因为不知何故,患者 1 和供应商 1 已被删除,对于例子)。仅出于这个原因,我更喜欢 @Akash 所示的解决方案 - 除了它可能是 EF 唯一有效且干净的解决方案这一事实之外。
If I understand correctly you want to have an address collection in your
Patient
,Vendor
, etc...... and somehow tell EF that
Patient.Addresses
only gets populated with addresses of address type "Patient".I think that is not possible for several reasons:
If you don't expose the foreign key in
Address
(noEntityKey
property there) you have to tell EF the key in the mapping (otherwise it would create/assume two different FK columns):This throws an exception due to the duplicate "EntityKey" column for two different relationships.
Next thing we could try is to expose the foreign key as property in
Address
(EntityKey
property is there) and then use this mapping:This (surprisingly) doesn't throw an exception but creates two FK constraints in the database between
Patient
-Address
andVendor
-Address
with the same FK columnEntityKey
. For your model, I think, this doesn't make sense because it would require that always aPatient
and aVendor
with the same PK exists if you have an address with someEntityKey
. So, you would have to remove these FK constraints in the DB manually (which feels very hacky to me).And the last thing is that you cannot specify a filter for lazy and eager loading of navigation properties. The
Addresses
collection would always get populated with the addresses which have the sameEntityKey
as the PK ofPatient
orVendor
respectively. You can apply a filter though with explicite loading:But you would have to ensure that you never use lazy or eager loading for the
Addresses
collection. So, this is not really a solution and we should forget it immediately.The ugliest point for me is that you cannot have FK constraints on the
EntityKey
. In other words: The DB allows to have an EntityKey = 1 with no referencedPatient
orVendor
with that PK (because somehow the patient 1 and vendor 1 have been deleted, for example).For this reason alone I would prefer the solution shown by @Akash - aside from the fact that it is probably the only working and clean solution with EF at all.