简体   繁体   English

在Entity Framework中获取被忽略的属性

[英]Get ignored properties in Entity Framework

I work on a framework with EF. 我在EF的框架上工作。 I want to get all ignored properties of an entity to build some special queries. 我想获取实体的所有被忽略的属性来构建一些特殊的查询。 How can I do it? 我该怎么做?

public class Customer
{
    public int Id { get; set; }
    public DateTime BirthDate { get; set; }
    public int Age { get; set; }
}

public class CustomerContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Customer>().Ignore(customer => customer.Age);
        base.OnModelCreating(modelBuilder);
    }

    public DbSet<Customer> Customers { get; set; }
}

public static class DbContextExtensions
{
    public static List<string> GetIgnoredProperties(this DbContext context, string entityTypeName)
    {
         // ???
    }
}

I know this is not answering your original question, and in my comments I mentioned that you should use reflection, but that was only because I read your question wrong. 我知道这不是回答你原来的问题,在我的评论中我提到你应该使用反思,但这只是因为我读错了你的问题。

Here is an alternative using reflection, for if you do not come right. 如果你不对,那么这是一个使用反射的替代方案。

If you assign the [NotMapped] attribute to the properties on your class that you would like to ignore, you could possibly retrieve all [NotMapped] properties using reflection. 如果将[NotMapped]属性分配给要忽略的类的属性,则可以使用反射检索所有[NotMapped]属性。 Below is an example of how this could be achieved. 以下是如何实现这一目标的示例。

var resultArray = yourClassInstance.GetType().GetProperties()
                            .Where(prop => Attribute.IsDefined(prop, typeof(NotMappedAttribute)));

Hope this helps you in some way. 希望这能以某种方式帮助你。

You can achieve what you want by calling the DbModelBuilder.Build . 您可以通过调用DbModelBuilder.Build来实现您想要的功能 It will create a DbModel base on configuration setup by the DbModelBuilder . 它将基于DbModelBuilder的配置设置创建DbModel The DbModel expose a ConceptualModel that hold the types used by the context. DbModel公开了一个ConceptualModel ,它包含上下文使用的类型。 The EdmModel hold each type that are declared in the context, and for each type, it hold the properties that has not been ignored by the DbModelBuilder during it's configuration. EdmModel保存在上下文中声明的每种类型,对于每种类型,它保存DbModelBuilder在配置期间未被忽略的属性。 So, to achieve what you want, you have to intersect the properties of each entity type with those present in the EdmModel . 因此,要实现您想要的,您必须将每个实体类型的属性与EdmModel中存在的属性相交。 It will give the delta between them, thefore the ignored properties. 它将给出它们之间的增量,然后是被忽略的属性。 Here an example : 这是一个例子:

public class CustomerContext : DbContext
{
    private static IReadOnlyDictionary<Type, IReadOnlyCollection<PropertyInfo>> _ignoredProperties;
    /// Hold the ignored properties configured from fluent mapping
    public static IReadOnlyDictionary<Type, IReadOnlyCollection<PropertyInfo>> IgnoredProperties
    {
        get
        {
            return _ignoredProperties;
        }
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Customer>().Ignore(customer => customer.Age);

        // Build ignored properties only if they are not                
        if (_ignoredProperties == null)
        {                
            var model = modelBuilder.Build(this.Database.Connection);                
            var mappedEntityTypes = new Dictionary<Type, IReadOnlyCollection<PropertyInfo>>();
            foreach (var entityType in model.ConceptualModel.EntityTypes)
            {
                var type = Type.GetType(entityType.FullName);
                var typeProperties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
                var mappedProperties = entityType.DeclaredProperties.Select(t => t.Name)
                    .Union(entityType.NavigationProperties.Select(t => t.Name));
                mappedEntityTypes.Add(type, new ReadOnlyCollection<PropertyInfo>(
                    typeProperties.Where(t => !mappedProperties.Contains(t.Name)).ToList()));
            }
            _ignoredProperties = new ReadOnlyDictionary<Type, IReadOnlyCollection<PropertyInfo>>(mappedEntityTypes);
        }

        base.OnModelCreating(modelBuilder);
    }

    public DbSet<Customer> Customers { get; set; }
}

The IgnoreProperties property is a singleton that will be initialized the first time you will use the context. IgnoreProperties属性是一个单例,将在您第一次使用上下文时进行初始化。 It will be null before that, so will have to ensure that nothing use it until it's initialized. 在此之前它将为null,因此必须确保在初始化之前不会使用它。 It's readonly, so you don't have to worrie about accidental clear of the collection. 这是只读的,所以你不必担心意外清除收藏品。 The entity type is used as key, and the value expose a collection that hold ignored properties. 实体类型用作键,值显示包含忽略属性的集合。 Example of use : 使用示例:

var properties = CustomerContext.IgnoredProperties[typeof(Customer)];

Cons : 缺点:

With this approach is that the DbModel will be built twice, one time to gather the ignored properties, and second time by EntityFramework when the DbCompiledModel will be cached for futur ObjectContext creation. 使用这种方法是DbModel将被构建两次,一次用于收集被忽略的属性,第二次由EntityFramework 构建 ,当DbCompiledModel将被缓存以进行futur ObjectContext创建。 It can have an impact on the cold start of the DbContext , it means that the fist time you will execute a query over your context, it will be a bit slower. 它可以对DbContext的冷启动产生影响,这意味着你第一次对上下文执行查询时,它会慢一点。 It will depend on the size of the DbContext . 它将取决于DbContext的大小。 Warm queries should not suffer. 热烈的询问不应受到影响。 OnModelCreating will be called once anyway . 无论如何,OnModelCreating将被调用一次

Pros : 优点:

All changes made on de DbModelBuilder configuration will be automatically reflected in the IgnoredProperties property. 对de DbModelBuilder配置所做的所有更改将自动反映在IgnoredProperties属性中。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM