在MVC 4和EF 5我要运行动态查询。
var returndata = Context.Database.SqlQuery(Type, strsql, null);
我不知道,有多少个字段将返回和名称。 出于这种结果我想打表的结构,显示在图。
问:我应该为类型传递什么?
我的查询返回的结果如下:
字段1,字段2,字段3,字段4,字段5
ROW1 ...
行2 ..
欣赏任何建议。
在MVC 4和EF 5我要运行动态查询。
var returndata = Context.Database.SqlQuery(Type, strsql, null);
我不知道,有多少个字段将返回和名称。 出于这种结果我想打表的结构,显示在图。
问:我应该为类型传递什么?
我的查询返回的结果如下:
字段1,字段2,字段3,字段4,字段5
ROW1 ...
行2 ..
欣赏任何建议。
你可以使用原始的SQL查询,因为EF不支持:
private static IEnumerable<object[]> Read(DbDataReader reader)
{
while (reader.Read())
{
var values = new List<object>();
for (int i = 0; i < reader.FieldCount; i++)
{
values.Add(reader.GetValue(i));
}
yield return values.ToArray();
}
}
然后:
public ActionResult Index()
{
using (var ctx = new UsersContext())
using (var cmd = ctx.Database.Connection.CreateCommand())
{
ctx.Database.Connection.Open();
cmd.CommandText = "SELECT * FROM UserProfile";
using (var reader = cmd.ExecuteReader())
{
var model = Read(reader).ToList();
return View(model);
}
}
}
终于在自己的看法:
@model IEnumerable<object[]>
<table>
<tbody>
@foreach (var row in Model)
{
<tr>
@foreach (var column in row)
{
<td>@column</td>
}
</tr>
}
</tbody>
</table>
这种方法加载来自SQL数据(具有参数)选择的行的列表中,其中每行是列的字典(关键是列名)。
private static List<Dictionary<string, object>> LoadData(string sqlSelect, params object[] sqlParameters)
{
var table = new List<Dictionary<string, object>>();
using (var ctx = new DbEntities())
{
ctx.Database.Connection.Open();
using (var cmd = ctx.Database.Connection.CreateCommand())
{
cmd.CommandText = sqlSelect;
foreach (var param in sqlParameters)
cmd.Parameters.Add(param);
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
var row = new Dictionary<string, object>();
for (int i = 0; i < reader.FieldCount; i++)
row[reader.GetName(i)] = reader[i];
table.Add(row);
}
}
}
}
return table;
}
最后我提出使用由“Mortalus”和ExpandoObject对象建议TypeBuilder选项。 它现在几乎没有性能开销。
就拿Typebuilder代码“Mortalus”的答案,然后我按照下面我规定而作出的代码。
List<Dictionary<string, object>> expandolist = new List<Dictionary<string, object>>();
foreach (var item in returndata)
{
IDictionary<string, object> expando = new ExpandoObject();
foreach (PropertyDescriptor propertyDescriptor in TypeDescriptor.GetProperties(item))
{
var obj = propertyDescriptor.GetValue(item);
expando.Add(propertyDescriptor.Name, obj);
}
expandolist.Add(new Dictionary<string, object>(expando));
}
return expandolist;
所以现在,我从动态对象“字典”的对象。 并使用它,你可以在设计时轻松地工作而不是等到运行时使用“动态”的对象。
不知道有关返回的类型什么,我想你可能是出于运气。
如果你知道它的模式可能在下跌,你可以使用一些try { } catch () { }
的上你的,否则动态查询匹配参数的接口,但看起来它可能是一个有点痛苦。
不幸的是,除非它知道他们的EF不会兑现的对象Type
。
如果这是你真正需要的,我想你最好的选择将是回落到ADO.NET
和DataTable
。
由达林季米特洛夫同样的职位,但它返回的DataTable
public DataTable QueryToTable(Entities db, string queryText, SqlParameter[] parametes)
{
using ( DbDataAdapter adapter = new SqlDataAdapter())
{
adapter.SelectCommand = db.Database.Connection.CreateCommand();
adapter.SelectCommand.CommandText = queryText;
if (parametes != null)
adapter.SelectCommand.Parameters.AddRange(parametes);
DataTable table = new DataTable();
adapter.Fill(table);
return table;
}
}
使用
SqlParameter[] parametes = new[]
{
new SqlParameter("date_from", dateFrom)
};
DataTable tab = QueryToTable(new Entities(),
"Select * From SomeTable Where ADate >= @date_from", parametes);
例如用于MS SQL服务器
我最近偶然发现了这个例子:
http://www.markzhou.com/blog/post/2011/06/02/Use-dynamic-type-in-Entity-Framework-41-SqlQuery()-method.aspx
我还没有测试它自己的时间,但它似乎是可能的一些额外的工作,建立了动态类型。
总之,你会想要做这样的事情:
TypeBuilder builder = Program.CreateTypeBuilder(
"MyDynamicAssembly", "MyModule", "MyType");
Program.CreateAutoImplementedProperty(builder, "name", typeof(string));
Program.CreateAutoImplementedProperty(builder, "type", typeof(string));
Program.CreateAutoImplementedProperty(builder, "id", typeof(int));
Type resultType = builder.CreateType();
dynamic queryResult = context.Database.SqlQuery(
resultType, "SELECT * FROM sys.sysobjects");
凡TypeBuilder
在细节在后描述我重视。
添加到切赫Voborník的回答,动态查询,我想补充的ResultSet的动态插入,我的应用程序需要整个数据库的所有表的动态查询,一大块的时间和随后的动态结果插入到远程数据库中,使用始终处于加密(此处省略)。 传递一个SB命令和参数对象。
public void StoreData(DbContext dbContext, Dictionary<string, string> columnInfo, List<Dictionary<string, object>> multiInsertObj, string tableName)
{
_ctx = dbContext;
_columnInfo = columnInfo;
var sb = new StringBuilder();
sb.Append(BuildSqlCommand(tableName, columnInfo, multiInsertObj.Count));
ExecuteSqlCommand(sb, GetParamsObject(columnInfo, multiInsertObj));
}
private static StringBuilder BuildSqlCommand(string tableName, Dictionary<string, string> variableInfo, int variableCount)
{
//Build sql command
var sb = new StringBuilder();
sb.Append("INSERT INTO dbo." + tableName + "(");
foreach (var variable in variableInfo)
{
sb.Append(variable.Key);
sb.Append(", ");
}
sb.Append("SystemNumber, ");
sb.Remove(sb.Length - 2, 2).Append(") VALUES ");
for (var i = 0; i < variableCount; i++)
{
sb.Append("(");
foreach (var name in variableInfo.Keys)
{
sb.Append("@" + name + "_" + i + ",");
}
sb.Append("@SystemNumber" + "_" + i + ",");
sb.Remove(sb.Length - 1, 1).Append("),");
}
sb.Remove(sb.Length - 1, 1);
return sb;
}
private static object[] GetParamsObject(Dictionary<string, string> columnInfo, List<Dictionary<string, object>> multiInsertObj)
{
var variableCount = multiInsertObj.Count;
var rowCount = multiInsertObj[0].Keys.Count;
var objectLength = (rowCount + 1) * variableCount;
var variableDataTypes = columnInfo.Values.ToList();
var paramObj = new object[objectLength];
var j = 0;
var i = 0;
foreach (var row in multiInsertObj)
{
var k = 0;
foreach (var data in row)
{
var sb = new StringBuilder();
sb.Append("@");
sb.Append(data.Key);
sb.Append("_" + i);
paramObj[j] = new SqlParameter(sb.ToString(), SetSqlDataType(variableDataTypes[k])) { Direction = Input, Value = data.Value };
j++;
k++;
}
paramObj[j] = new SqlParameter(("@SystemNumber" + "_" + i), SetSqlDataType("int")) { Direction = Input, Value = _systemNumber };
i++;
j++;
}
return paramObj;
}
private static void ExecuteSqlCommand(StringBuilder sb, params object[] sqlParameters)
{
using (_ctx)
{
_ctx.Database.Connection.Open();
using (var cmd = _ctx.Database.Connection.CreateCommand())
{
cmd.CommandText = sb.ToString();
foreach (var param in sqlParameters)
cmd.Parameters.Add(param);
try
{
cmd.ExecuteNonQuery();
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
}
}