복붙노트

[SQL] SQL 쿼리 실행 엔티티 프레임 워크에서 익명 유형 결과

SQL

SQL 쿼리 실행 엔티티 프레임 워크에서 익명 유형 결과

나는 .NET 프레임 워크 4.0 코드 첫 번째 방법으로 엔티티 프레임 워크 5.0을 사용하고 있습니다. 지금은 내가 따라 엔티티 프레임 워크에 원시 SQL을 실행할 수 있다는 것을 알고

var students = Context.Database.SqlQuery<Student>("select * from student").ToList();

그것은 완벽하게 작동하지만 내가 원하는 것은 익명의 결과를 돌려주고 있어요. 다음과 같은 예를 들어 나는 학생 테이블에서 특정 컬럼을 원하는

var students = Context.Database.SqlQuery<Student>("select FirstName from student").ToList();

그것은 작동하지 않습니다. 그것은 예외를 제공합니다

나는 동적 유형을 시도 그래서

var students = Context.Database.SqlQuery<dynamic>("select FirstName from student").ToList();

그것은 또한 빈 객체를 반환, 작동하지 않습니다. 그것은에서 사용할 수있는 데이터가 없습니다.

동적 SQL 쿼리에서 익명 형식의 결과를 얻을 수있는 방법이 있습니까?

해결법

  1. ==============================

    1.당신은 그 원시 SQL을 사용해야 엔티티 프레임 워크 SQL 쿼리 알려진 유형의 개체에 대한 것입니다에만 작동합니다.

    당신은 그 원시 SQL을 사용해야 엔티티 프레임 워크 SQL 쿼리 알려진 유형의 개체에 대한 것입니다에만 작동합니다.

    여기에 방법 I 사용은 다음과 같습니다

    public static IEnumerable<dynamic> DynamicListFromSql(this DbContext db, string Sql, Dictionary<string, object> Params)
    {
        using (var cmd = db.Database.Connection.CreateCommand())
        {
            cmd.CommandText = Sql;
            if (cmd.Connection.State != ConnectionState.Open) { cmd.Connection.Open(); }
    
            foreach (KeyValuePair<string, object> p in Params)
            {
                DbParameter dbParameter = cmd.CreateParameter();
                dbParameter.ParameterName = p.Key;
                dbParameter.Value = p.Value;
                cmd.Parameters.Add(dbParameter);
            }
    
            using (var dataReader = cmd.ExecuteReader())
            {
                while (dataReader.Read())
                {
                    var row = new ExpandoObject() as IDictionary<string, object>;
                    for (var fieldCount = 0; fieldCount < dataReader.FieldCount; fieldCount++)
                    {
                        row.Add(dataReader.GetName(fieldCount), dataReader[fieldCount]);
                    }
                    yield return row;
                }
            }
        }
    }
    

    이처럼 호출 할 수 있습니다 :

    List<dynamic> results = DynamicListFromSql(myDb,"select * from table where a=@a and b=@b", new Dictionary<string, object> { { "a", true }, { "b", false } }).ToList();
    
  2. ==============================

    2.다음은 나를 위해 벌금을 일 최종 솔루션입니다.

    다음은 나를 위해 벌금을 일 최종 솔루션입니다.

    public static System.Collections.IEnumerable DynamicSqlQuery(this Database database, string sql, params object[] parameters)
            {
                TypeBuilder builder = createTypeBuilder(
                        "MyDynamicAssembly", "MyDynamicModule", "MyDynamicType");
    
                using (System.Data.IDbCommand command = database.Connection.CreateCommand())
                {
                    try
                    {
                        database.Connection.Open();
                        command.CommandText = sql;
                        command.CommandTimeout = command.Connection.ConnectionTimeout;
                        foreach (var param in parameters)
                        {
                            command.Parameters.Add(param);
                        }
    
                        using (System.Data.IDataReader reader = command.ExecuteReader())
                        {
                            var schema = reader.GetSchemaTable();
    
                            foreach (System.Data.DataRow row in schema.Rows)
                            {
                                string name = (string)row["ColumnName"];
                                //var a=row.ItemArray.Select(d=>d.)
                                Type 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();
                        command.Parameters.Clear();
                    }
                }
    
                Type resultType = builder.CreateType();
    
                return database.SqlQuery(resultType, sql, parameters);
            }
    
            private 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;
            }
    
            private 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);
            }    
    
  3. ==============================

    3.당신은 여기에서 코드를 시도 아래로 스크롤 stankovski의 구현 찾을 수 있습니다 : http://www.codeproject.com/Articles/206416/Use-dynamic-type-in-Entity-Framework-SqlQuery

    당신은 여기에서 코드를 시도 아래로 스크롤 stankovski의 구현 찾을 수 있습니다 : http://www.codeproject.com/Articles/206416/Use-dynamic-type-in-Entity-Framework-SqlQuery

    정적 클래스에 코드를 복사 한 후, 당신은 당신이 원하는 것을 얻을이 함수를 호출 할 수 있습니다 :

    var students = Context.Database.DynamicSqlQuery("select FirstName from student").ToList()
    
  4. ==============================

    4.당신이 엔티티를 가지고 만하려는 경우 속성 중 일부는 반사의 도움으로 더 나은 솔루션을 얻을 수 있습니다 백업합니다.

    당신이 엔티티를 가지고 만하려는 경우 속성 중 일부는 반사의 도움으로 더 나은 솔루션을 얻을 수 있습니다 백업합니다.

    이 코드는 위의 답변에서와 동일한 샘플을 축적.

    이 외에도 당신은 유형과 다시 싶어 필드의 배열을 지정할 수 있습니다.

    그 결과 유형을 IEnumerable이다.

    public static class DatabaseExtension
    {
        public static IEnumerable<T> DynamicSqlQuery<T>(this Database database, string[] fields, string sql, params object[] parameters) where T : new()
        {
            var type = typeof (T);
    
            var builder = CreateTypeBuilder("MyDynamicAssembly", "MyDynamicModule", "MyDynamicType");
    
            foreach (var field in fields)
            {
                var prop = type.GetProperty(field);
                var propertyType = prop.PropertyType;
                CreateAutoImplementedProperty(builder, field, propertyType);
            }
    
            var resultType = builder.CreateType();
    
            var items = database.SqlQuery(resultType, sql, parameters);
            foreach (object item in items)
            {
                var obj = new T();
                var itemType = item.GetType();
                foreach (var prop in itemType.GetProperties(BindingFlags.Instance | BindingFlags.Public))
                {
                    var name = prop.Name;
                    var value = prop.GetValue(item, null);
                    type.GetProperty(name).SetValue(obj, value);
                }
                yield return obj;
            }
        }
    
        private 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;
        }
    
        private 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, 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);
        }    
    }
    

    당신은 이런 식으로 호출 할 수 있습니다 :

    var fields = new[]{ "Id", "FirstName", "LastName" };
    var sql = string.Format("SELECT {0} FROM People WHERE Id = @id", string.Join(", ", fields));
    
    var person = db.Database.DynamicSqlQuery<People>(fields, sql, new SqlParameter("id", id))
        .FirstOrDefault();
    

    사실 그것은 단순한 유형에서 작동 및 오류 처리가 없습니다.

  5. ==============================

    5.나는 그런 식으로 그것을 사용

    나는 그런 식으로 그것을 사용

    ORMClass :

    public class ORMBase<T, TContext> : IORM<T>
            where T : class
            where TContext : DbContext, IDisposable, new()
    

    방법:

    public IList<TResult> GetSqlQuery<TResult>(string sql, params object[] sqlParams)
    {
                    using (TContext con = new TContext())
                    {
                        return Enumerable.ToList(con.Database.SqlQuery<TResult>(sql, sqlParams));
                    }
    }
    

    그리고 마지막으로 사용

    public class ResimORM : ORMBase<Resim, mdlOgrenciKulup>, IDisposable
    {
        public void Dispose() { GC.SuppressFinalize(this); }
    }
    
    
    
    
    
    ResimORM RE_ORM = new ResimORM();
    List<Resim> a = RE_ORM.GetSqlQuery<Resim>(sql,null).ToList();
    int b = RE_ORM.GetSqlQuery<int>(sql,null).FirstOrDefault();
    
  6. from https://stackoverflow.com/questions/26749429/anonymous-type-result-from-sql-query-execution-entity-framework by cc-by-sa and MIT license