zoukankan      html  css  js  c++  java
  • EF 6.x和EF Core实现返回dynamic类型

    前言

    未曾想需要直接返回dynamic,多次尝试未能实现,最终还是在stackoverflow上找到了解决方案,特此备忘录。

            public static dynamic SqlQuery(this Database database, string sql, params object[] parameters)
            {
                TypeBuilder builder = CreateTypeBuilder(
                        "DynamicAssembly", "DynamicModule", "DynamicType");
    
                using (var cmd = database.Connection.CreateCommand())
                {
                    try
                    {
                        cmd.CommandText = sql;
    
                        if (cmd.Connection.State != ConnectionState.Open)
                        {
                            cmd.Connection.Open();
                        }
    
                        cmd.CommandTimeout = cmd.Connection.ConnectionTimeout;
    
                        foreach (var param in parameters)
                        {
                            cmd.Parameters.Add(param);
                        }
    
                        using (IDataReader reader = cmd.ExecuteReader())
                        {
                            var schema = reader.GetSchemaTable();
    
                            foreach (DataRow row in schema.Rows)
                            {
                                var name = (string)row["ColumnName"];
                                var type = (Type)row["DataType"];
                                if (type != typeof(string) && (bool)row.ItemArray[schema.Columns.IndexOf("AllowDbNull")])
                                {
                                    type = typeof(Nullable<>).MakeGenericType(type);
                                }
                                CreateAutoImplementedProperty(builder, name, type);
                            }
                        }
                    }
                    finally
                    {
                        database.Connection.Close();
                        cmd.Parameters.Clear();
                    }
                }
    
                var resultType = builder.CreateType();
    
                return database.SqlQuery(resultType, sql, parameters);
            }
    
            public static TypeBuilder CreateTypeBuilder(
                  string assemblyName, string moduleName, string typeName)
            {
                TypeBuilder typeBuilder = AppDomain
                    .CurrentDomain
                    .DefineDynamicAssembly(new AssemblyName(assemblyName), AssemblyBuilderAccess.Run)
                    .DefineDynamicModule(moduleName)
                    .DefineType(typeName, TypeAttributes.Public);
                typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
                return typeBuilder;
            }
    
            public static void CreateAutoImplementedProperty(
                TypeBuilder builder, string propertyName, Type propertyType)
            {
                const string PrivateFieldPrefix = "m_";
                const string GetterPrefix = "get_";
                const string SetterPrefix = "set_";
    
                // Generate the field.
                FieldBuilder fieldBuilder = builder.DefineField(
                    string.Concat(PrivateFieldPrefix, propertyName), propertyType, FieldAttributes.Private);
    
                // Generate the property
                PropertyBuilder propertyBuilder = builder.DefineProperty(
                    propertyName, System.Reflection.PropertyAttributes.HasDefault, propertyType, null);
    
                // Property getter and setter attributes.
                MethodAttributes propertyMethodAttributes =
                    MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
    
                // Define the getter method.
                MethodBuilder getterMethod = builder.DefineMethod(
                    string.Concat(GetterPrefix, propertyName),
                    propertyMethodAttributes, propertyType, Type.EmptyTypes);
    
                // Emit the IL code.
                // ldarg.0
                // ldfld,_field
                // ret
                ILGenerator getterILCode = getterMethod.GetILGenerator();
                getterILCode.Emit(OpCodes.Ldarg_0);
                getterILCode.Emit(OpCodes.Ldfld, fieldBuilder);
                getterILCode.Emit(OpCodes.Ret);
    
                // Define the setter method.
                MethodBuilder setterMethod = builder.DefineMethod(
                    string.Concat(SetterPrefix, propertyName),
                    propertyMethodAttributes, null, new Type[] { propertyType });
    
                // Emit the IL code.
                // ldarg.0
                // ldarg.1
                // stfld,_field
                // ret
                ILGenerator setterILCode = setterMethod.GetILGenerator();
                setterILCode.Emit(OpCodes.Ldarg_0);
                setterILCode.Emit(OpCodes.Ldarg_1);
                setterILCode.Emit(OpCodes.Stfld, fieldBuilder);
                setterILCode.Emit(OpCodes.Ret);
    
                propertyBuilder.SetGetMethod(getterMethod);
                propertyBuilder.SetSetMethod(setterMethod);
            }
                using (var ctx = new EfDbContext())
                {
                    ctx.Database.Log = Console.WriteLine;
    
                    dynamic queryResult = ctx.Database.SqlQuery("select o.*,c.Name from dbo.Orders as o left join dbo.Customers as c on o.CustomerId = c.Id");
                    var ordersJson = JsonConvert.SerializeObject(queryResult);
                    var orders = JsonConvert.DeserializeObject<List<Order>>(ordersJson);
                };

    来自于:https://stackoverflow.com/questions/26749429/anonymous-type-result-from-sql-query-execution-entity-framework

  • 相关阅读:
    web安全——代理(nginx)
    2016年3-7月书单推荐
    web安全——系统(Linux)
    web安全——防火墙
    web安全——简介
    系统安全扫描工具(appscan)的扫描类型小记
    知识管理,让生活更美好
    亚马逊如何变成 SOA(面向服务的架构)
    徐小平:关了公司以后,我有这些话要对你说
    网易味央第二座猪场落户江西 面积超过3300亩
  • 原文地址:https://www.cnblogs.com/CreateMyself/p/8935560.html
Copyright © 2011-2022 走看看