简体   繁体   English

我可以在Entity Framework 6中的关系中的属性上定义过滤器吗?

[英]Can I define a filter on a property within a relationship in Entity Framework 6?

Before I get started, note that I've simplified the data structure for what I'm trying to do and in the real world it isn't as awful of an implementation as you might think. 在开始之前,请注意我已经简化了我正在尝试做的事情的数据结构,而在现实世界中,它并不像您想象的那样糟糕。 Or maybe it is. 或者也许是。 Regardless, I can't change the way the data is structured so I'm not looking for suggestions on how to better structure the data. 无论如何,我无法改变数据结构的方式,所以我不是在寻找有关如何更好地构建数据的建议。 I'm just hoping to see if there is a way I can do what I'm asking in Entity Framework 6. 我只是希望看看我是否有办法在Entity Framework 6中做我所要求的。

Consider I have the following tables: 考虑我有以下表格:

Person: 人:

ID    FirstName    LastName
1     John         Smith
2     Jane         Doe

Job: 工作:

ID    Name
1     Developer

ExtendedData: ExtendedData:

ID    TableName    RowID    FieldName      FieldValue
1     Person       1        MiddleInitial  A
2     Person       1        Gender         M
3     Person       2        MiddleInitial  B
4     Person       2        Gender         F
5     Job          1        Description    Develop Stuff

The purpose of this ExtendedData table is to allow for additional data to be stored when there isn't a column for the data. 此ExtendedData表的目的是允许在没有数据列时存储其他数据。 For example, here "MiddleInitial" is not a column in the Person table, but in the ExtendedData table we can add a row to store that data. 例如,这里“MiddleInitial”不是Person表中的列,但是在ExtendedData表中我们可以添加一行来存储该数据。

In my "Person" class I can add the following code to add an ExtendedData property: 在我的“Person”类中,我可以添加以下代码来添加ExtendedData属性:

public virtual ICollection<ExtendedData> ExtendedData { get; set; }

Then I can create a relationship in Entity Framework with this: 然后我可以在Entity Framework中创建一个关系:

modelBuilder.Entity<Person>()
    .HasMany(e => e.ExtendedData)
    .WithRequired(e => e.Person)
    .HasForeignKey(e => e.RowID);

The concern I have, is if I call... 我所关心的是,如果我打电话......

john = Persons.Where(a => a.ID == 1);
john.ExtendedData...

... I'll get back all Extended Data rows where RowID = 1, including the row for the "Job" table. ...我将返回RowID = 1的所有扩展数据行,包括“作业”表的行。 Obviously, I could do something like... 显然,我可以做点像......

john.ExtendedData.Where(a => a.TableName == "Person")...

... but this is a little dangerous because what if I (or some other developer) forget to specify that extra filter in the code? ...但这有点危险,因为如果我(或其他一些开发人员)忘记在代码中指定额外的过滤器呢?

I tried doing something like this... 我尝试过做这样的事......

modelBuilder.Entity<Person>()
    .HasMany(e => (ICollection<ExtendedData>))e.ExtendedData.Where(a => a.TableName == "Person"))
    .WithRequired(e => e.Person)
    .HasForeignKey(e => e.RowID);

... but received an error at run time stating... ...但在运行时收到错误说明......

The expression 'e => Convert(e.ExtendedData.Where(a => (a.TableName == "Person")))' is not a valid property expression. 表达式'e => Convert(e.ExtendedData.Where(a =>(a.TableName ==“Person”)))''不是有效的属性表达式。 The expression should represent a property: C#: 't => t.MyProperty' VB.Net: 'Function(t) t.MyProperty'. 表达式应代表一个属性:C#:'t => t.MyProperty'VB.Net:'Punction(t)t.MyProperty'。

The sense I make of it is it wants me to specify a property from "e" and not try to do any further wizardry. 我对它的感觉是它要我从“e”中指定一个属性而不是尝试做任何进一步的魔法。

Is there anywhere I can modify the Entity Framework model such that when I call person.ExtendedData it will only return to me ExtendedData records where the TableName = "Person"? 有没有我可以修改实体框架模型的地方,这样当我调用person.ExtendedData时,它只会返回给我的TableData =“Person”的ExtendedData记录? Or must I remember to always include that extra filter when trying to pull data from the ExtendedData table? 或者我是否记得在尝试从ExtendedData表中提取数据时始终包含额外的过滤器?

What you really want here is Table Per Hierarchy. 你真正想要的是Table Per Hierarchy。 Define a base entity for your table, then define an inherited entity for each variation, and customize the discriminator. 为表定义基本实体,然后为每个变体定义一个继承的实体,并自定义鉴别器。

Public abstract class ExtendedData
{
    public int Id {get;set;}
    public string FieldName {get;set;}
    public string FieldValue {get;set;}
}

public class ExtendedPersonData : ExtendedData
{}

public class ExtendedJobData : ExtendedData
{}

public class Person
{
    ....
    public virtual ICollection<ExtendedPersonData> ExtendedData {get;set}
}

public class Job
{
    ....
    public virtual ICollection<ExtendedJobData> ExtendedData {get;set;}
}

public class Context : DbContext
{
    ....
    public DbSet<ExtendedData> ExtendedData {get;set;}
} 

modelBuilder.Entity<ExtendedData>()
    .Map<ExtendedPersonData>(m => m.Requires("TableName").HasValue("Person"))
    .Map<ExtendedJobData>(m => m.Requires("TableName").HasValue("Job"));

with the inherited classes, you can now do Non-Polymorphic Queries against the table data, ie 使用继承的类,您现在可以对表数据执行非多态查询,即

IQueryable<ExtendedPersonData> query = from e in context.ExtendedData
                                                .OfType<ExtendedPersonData>()
                                       select e;

This will generate a SQL query which only returns records where the discriminator column matches ( "TableName" == "Person" in this case). 这将生成一个SQL查询,该查询仅返回鉴别器列匹配的记录(在本例中为"TableName" == "Person" )。 Returning a Person and querying it's ExtendedData would automatically create a Non-Polymorphic Query, due to the collection type defined on the entity. 由于在实体上定义的集合类型,返回Person并查询它的ExtendedData将自动创建非多态查询。

Note that in this scenario, you can mix shared columns and columns unique to each variation. 请注意,在此方案中,您可以混合每个变体唯一的共享列和列。 Any columns specific to a unique variation would automatically become nullable in the table, and would only be filled by the entities that provide it. 任何特定于唯一变体的列都将在表中自动变为可为空,并且只能由提供它的实体填充。 In your case, however, you have no unique columns, so the Inherited classes are just implementation stubs. 但是,在您的情况下,您没有唯一列,因此Inherited类只是实现存根。

http://weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-1-table-per-hierarchy-tph http://weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-1-table-per-hierarchy-tph

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 实体框架:无法定义1:1关系 - Entity framework: Unable to define 1:1 relationship 我可以在Entity Framework Code First中为复杂类型定义一对多关系吗? - Can I define a one-to-many relationship on a complex type in Entity Framework Code First? 实体框架如何通过导航属性的属性过滤我的结果? - Entity Framework How can I filter my results by a property of a navigation property? 可以将Entity Framework配置为在没有数据库关系的情况下加载集合属性吗? - Can Entity Framework be configured to load a collection property where there is no database relationship? 在实体框架中定义集合而不创建关系 - Define collection in entity framework without creating relationship 我可以使用Entity Framework 4使用“ .include”加载层次结构数据并根据某些条件过滤导航属性吗? - Can I load hierarchical data with Entity Framework 4 using “.Include” and filter a Navigation Property based on some criteria 实体框架-如何过滤EntityCollection关系 - Entity Framework - How to filter an EntityCollection Relationship Entity Framework Core:填充关系导航属性 - Entity Framework Core : populating relationship navigation property Entity Framework Core 使用 UDF 定义属性 - Entity Framework Core define property using a UDF 在 Entity Framework Core 中,如果我定义这些关系,它会在两个实体之间创建循环关系吗? - In Entity Framework Core, if I define these relationships, will it create a cyclic relationship between two entities?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM