Man*_*iya 30 c# sql entity-framework anonymous-types
我使用实体框架5.0与.net framework 4.0代码的第一种方法.现在我知道我可以通过以下方式在实体框架中运行原始sql
var students = Context.Database.SqlQuery<Student>("select * from student").ToList();
Run Code Online (Sandbox Code Playgroud)
它工作得很好,但我想要的是返回匿名结果.例如,我只想要学生表中的特定列,如下所示
var students = Context.Database.SqlQuery<Student>("select FirstName from student").ToList();
Run Code Online (Sandbox Code Playgroud)
它不起作用.它给了例外
数据读取器与指定的"MyApp.DataContext.Student"不兼容.类型为"StudentId"的成员在数据读取器中没有具有相同名称的相应列.
所以我尝试过dynamic类型
var students = Context.Database.SqlQuery<dynamic>("select FirstName from student").ToList();
Run Code Online (Sandbox Code Playgroud)
它也不起作用,它返回一个空对象.没有数据可用.
有没有办法从动态SQL查询中获取匿名类型结果?
Man*_*iya 27
这是最终解决方案,对我来说很好.
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);
}
Run Code Online (Sandbox Code Playgroud)
Cht*_*lek 23
您必须使用原始Sql,权限框架SqlQuery<T>仅适用于具有已知类型的对象.
这是我使用的方法:
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;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
你可以这样称呼它:
List<dynamic> results = DynamicListFromSql(myDb,"select * from table where a=@a and b=@b", new Dictionary<string, object> { { "a", true }, { "b", false } }).ToList();
Run Code Online (Sandbox Code Playgroud)
您可以从这里尝试代码,向下滚动并找到stankovski的工具:http: //www.codeproject.com/Articles/206416/Use-dynamic-type-in-Entity-Framework-SqlQuery
将代码复制到静态类后,可以调用此函数来获得所需内容:
var students = Context.Database.DynamicSqlQuery("select FirstName from student").ToList()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
51365 次 |
| 最近记录: |