代码改变世界

Entity Framework 6 中如何获取 EntityTypeConfiguration 的 Edm 信息?(三)

  音乐让我说  阅读(227)  评论(0编辑  收藏  举报

接着上一篇,我们继续来优化。

直接贴代码了:

LambdaHelper.cs

复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace EntityFrameworkSample
{
    public static class LambdaHelper
    {
        public static string GetPropName<TEntityType, TProperty>(Expression<Func<TEntityType, TProperty>> propertyExpression)
        {
            MemberExpression memberExpression;
            if (!InspectIsMemberExpression<TEntityType, TProperty>(propertyExpression, true, out memberExpression))
            {
                return null;
            }
            return memberExpression.Member.Name;
        }

        public static bool InspectIsMemberExpression<TEntityType, TProperty>(Expression<Func<TEntityType, TProperty>> propertyExpression)
        {
            return InspectIsMemberExpression<TEntityType, TProperty>(propertyExpression, true);
        }

        public static bool InspectIsMemberExpression<TEntityType, TProperty>(Expression<Func<TEntityType, TProperty>> propertyExpression, bool throwExOnNull)
        {
            MemberExpression memberExpression;
            return InspectIsMemberExpression<TEntityType, TProperty>(propertyExpression, throwExOnNull, out memberExpression);
        }

        public static bool InspectIsMemberExpression<TEntityType, TProperty>(Expression<Func<TEntityType, TProperty>> propertyExpression, bool throwExOnNull, out MemberExpression memberExpression)
        {
            if (propertyExpression == null)
            {
                throw new ArgumentNullException("express");
            }
            memberExpression = propertyExpression.Body as MemberExpression;
            if (memberExpression == null)
            {
                if (throwExOnNull)
                {
                    throw new ArgumentException("请为类型 \"" + typeof(TEntityType).FullName + "\" 的指定一个字段(Field)或属性(Property)作为 Lambda 的主体(Body)。");
                }
                return false;
            }
            return true;
        }
    }
}
复制代码

 

DbContextExtensions.cs

复制代码
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Core.Mapping;
using System.Data.Entity.Core.Metadata.Edm;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.ModelConfiguration;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Linq;
using EntityFramework.Extensions;
using System.Linq.Expressions;

namespace EntityFrameworkSample
{
    public enum AcquiredEdmType
    {
        TableName,

        FirstPrimaryKeyNameString,

        ColumnName
    }

    public static class DbContextExtensions
    {
        #region 基础方法

        public static string GetTableName<TEntity>(this DbContext context)
        {
            return GetTableName(context, typeof(TEntity));
        }

        public static string GetTableName(this DbContext context, Type type)
        {
            return GetTableNameOrColumnName(context, type, AcquiredEdmType.TableName);
        }

        public static string GetFirstPrimaryKeyName<TEntity>(this DbContext context)
        {
            return GetFirstPrimaryKeyName(context, typeof(TEntity));
        }

        public static string GetFirstPrimaryKeyName(this DbContext context, Type type)
        {
            return GetTableNameOrColumnName(context, type, AcquiredEdmType.FirstPrimaryKeyNameString);
        }

        public static string GetColumnName<TEntity, TProperty>(this DbContext context, Expression<Func<TEntity, TProperty>> propertyExpression)
        {
            return GetTableNameOrColumnName(context, typeof(TEntity), AcquiredEdmType.ColumnName, LambdaHelper.GetPropName(propertyExpression));
        }

        public static string GetColumnName(this DbContext context, Type type, string propertyName)
        {
            return GetTableNameOrColumnName(context, type, AcquiredEdmType.ColumnName, propertyName);
        }

        private static string GetTableNameOrColumnName(this DbContext context, Type type, AcquiredEdmType edmType, string propertyName = null)
        {
            var metadata = ((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace;

            // Get the part of the model that contains info about the actual CLR types
            ObjectItemCollection objectItemCollection = ((ObjectItemCollection)metadata.GetItemCollection(DataSpace.OSpace));

            // Get the entity type from the model that maps to the CLR type
            EntityType entityType = metadata
                    .GetItems<EntityType>(DataSpace.OSpace)
                          .Single(e => objectItemCollection.GetClrType(e) == type);

            // Get the entity set that uses this entity type
            EntitySet entitySet = metadata
                .GetItems<EntityContainer>(DataSpace.CSpace)
                      .Single()
                      .EntitySets
                      .Single(s => s.ElementType.Name == entityType.Name);

            // Find the mapping between conceptual and storage model for this entity set
            EntitySetMapping mapping = metadata.GetItems<EntityContainerMapping>(DataSpace.CSSpace)
                          .Single()
                          .EntitySetMappings
                          .Single(s => s.EntitySet == entitySet);

            // Find the storage entity set (table) that the entity is mapped
            EntitySet tableEntitySet = mapping
                .EntityTypeMappings.Single()
                .Fragments.Single()
                .StoreEntitySet;

            // Return the table name from the storage entity set
            object objTableName = tableEntitySet.MetadataProperties["Table"].Value;
            string tableName = objTableName == null ? tableEntitySet.Name : Convert.ToString(objTableName);

            switch (edmType)
            {
                case AcquiredEdmType.TableName:
                    return tableName;
                case AcquiredEdmType.FirstPrimaryKeyNameString:
                    {
                        var firstKeyProp = tableEntitySet.ElementType.KeyProperties[0];
                        //return tableName + "." + firstKeyProp.Name;
                        return firstKeyProp.Name;
                    }
                case AcquiredEdmType.ColumnName:
                    {
                        // Find the storage property (column) that the property is mapped
                        var columnName = mapping
                            .EntityTypeMappings.Single()
                            .Fragments.Single()
                            .PropertyMappings
                            .OfType<ScalarPropertyMapping>()
                                  .Single(m => m.Property.Name == propertyName)
                            .Column
                            .Name;

                        //return tableName + "." + columnName;
                        return columnName;
                    }
                default:
                    throw new ArgumentNullException("Invalid argument");
            }
        }

        #endregion

        #region 额外方法

        

        #endregion
    }
}
复制代码

 

Program.cs

复制代码
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Core.Mapping;
using System.Data.Entity.Core.Metadata.Edm;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.ModelConfiguration;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Linq;
using EntityFramework.Extensions;
using System.Linq.Expressions;
using EntityFrameworkSample;

namespace EntityFrameworkSample
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var context = new BloggingContext(@"Data Source=.\SQLExpress;Initial Catalog=TestDB;Persist Security Info=True;User ID=sa;Password=123456"))
            {
                string blogTableName = context.GetTableName<Blog>();
                string postTableName = context.GetTableName<Post>();

                Console.WriteLine("Blog maps to: {0}", blogTableName);
                Console.WriteLine("Post maps to: {0}", postTableName);

                string blogPrimaryKeyName = context.GetFirstPrimaryKeyName<Blog>();
                string postPrimaryKeyName = context.GetFirstPrimaryKeyName<Post>();

                Console.WriteLine("Blog primary key name: {0}", blogPrimaryKeyName);
                Console.WriteLine("Post primary key name: {0}", postPrimaryKeyName);

                //System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew();
                //for (int i = 0; i < 600000; i++)
                //{
                //    context.GetColumnName<Blog, string>(c => c.BlogUrl); //经过测试,循环60万次,耗时14秒
                //}
                //watch.Stop();
                //Console.WriteLine("耗时:{0}秒", (watch.ElapsedMilliseconds / 1000).ToString());

                string blogUrlColumnName = context.GetColumnName<Blog, string>(c => c.BlogUrl);
                string postTitleColumnName = context.GetColumnName<Post, string>(c => c.PostTitle);

                //Console.WriteLine("Blog.BlogUrl maps to: {0}.{1}", blogTableName, blogUrlColumnName);
                Console.WriteLine("Post.PostTitle maps to: {0}.{1}", postTableName, postTitleColumnName);

                
            }
            Console.ReadLine();
        }

        
    }

    public class BloggingContext : DbContext
    {
        public BloggingContext(string nameOrConnectionString)
            : base(nameOrConnectionString)
        {
            
        }

        public DbSet<Blog> Blogs { get; set; }
        public DbSet<Post> Posts { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Configurations.Add(new BlogMap());
            modelBuilder.Configurations.Add(new PostMap());
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
            base.OnModelCreating(modelBuilder);
        }
    }

    public class Blog
    {
        public int Id { get; set; }
        public string BlogUrl { get; set; }

        public List<Post> Posts { get; set; }
    }

    public class Post
    {
        public int Id { get; set; }
        public string PostTitle { get; set; }
        public string Body { get; set; }

        public int BlogId { get; set; }
        public Blog Blog { get; set; }
    }

    public class BlogMap : EntityTypeConfiguration<Blog>
    {
        public BlogMap()
        {
            this.HasKey(c => c.Id);
            this.ToTable("t_blog");
            this.Property(c => c.Id).HasColumnName("BlogId");
            this.Property(c => c.BlogUrl).HasColumnName("Url");
        }
    }

    public class PostMap : EntityTypeConfiguration<Post>
    {
        public PostMap()
        {
            this.HasKey(c => c.Id);
            this.ToTable("t_post");
            this.Property(c => c.Id).HasColumnName("PostId");
            this.Property(c => c.PostTitle).HasColumnName("Title");
        }
    }
}
复制代码

运行截图:

谢谢浏览!

点击右上角即可分享
微信分享提示