简体   繁体   English

使用实体框架中的SqlQuery RAW查询返回匿名类型

[英]Return Anonymous Type using SqlQuery RAW Query in Entity Framework

How can I make Entity Framework SqlQuery to return an Anonymous type. 如何使Entity Framework SqlQuery返回匿名类型。

Right now I run a context.TheObject.SqlQuery() RAW query. 现在我运行一个context.TheObject.SqlQuery() RAW查询。 the query joins two tables and I want to return the results of the joined tables. 查询连接两个表,我想返回连接表的结果。

If I use it with a type context.TheObject.SqlQuery() I only get to see the results of the table of that same type. 如果我使用类型context.TheObject.SqlQuery()我只能看到相同类型的表的结果。

I tried db.Database.SqlQuery<DbResults>("the sql query here") ; 我试过db.Database.SqlQuery<DbResults>("the sql query here") ; With a pre-defined class that matches the result's objects, but all the fields are null. 使用与结果对象匹配的预定义类,但所有字段均为null。

Using Entity Framework 6 with MySQL. 使用Entity Framework 6和MySQL。

I'm going out on a limb here, and will try to address your underlying problem instead of directly answering your question. 我在这里走出困境,并试图解决你的根本问题,而不是直接回答你的问题。

Your scenario with the pre-defined class should work . 您使用预定义类的方案应该有效 A likely pitfall is that the column names and the properties of your class did not match up. 一个可能的缺陷是列名和类的属性不匹配。

Sample code (LinqPad) 示例代码(LinqPad)

    var results = Database.SqlQuery<TestResult>("select r.Name, b.BankName from relation r inner join BankAccount b on b.RelationId = r.Id where r.Id = 2");
    results.Dump();
}

public class TestResult {
    public string Name { get; set; }
    public string BankName { get; set; }

I'd strongly advise you to revisit your problematic code using explicit types. 我强烈建议您使用显式类型重新访问有问题的代码。


In direct response to your question: no, you can't return anonymous types from SqlQuery. 直接回答你的问题:不,你不能从SqlQuery返回匿名类型。 The best you can do is build dynamic objects , but that unfortunately requires a fair bit of manual work using TypeBuilder. 您可以做的最好的是构建动态对象 ,但不幸的是,使用TypeBuilder需要相当多的手动工作。 See http://www.codeproject.com/Articles/206416/Use-dynamic-type-in-Entity-Framework-SqlQuery for a sample. 有关示例,请参见http://www.codeproject.com/Articles/206416/Use-dynamic-type-in​​-Entity-Framework-SqlQuery

Here's what I did. 这就是我做的。

  1. Execute sp and get the results into a data reader 执行sp并将结果输入数据读取器
public static async Task<IEnumerable<object>> GetAnonymousResults(IUnitOfWork unitOfWork, string spName, SqlParameter[] outParameters, params SqlParameter[] parameters)
        {

            //meh, you only need the context here. I happened to use UnitOfWork pattern and hence this.
            var context = unitOfWork as DbContext;

            DbCommand command = new SqlCommand();
            command.CommandType = CommandType.StoredProcedure;
            command.CommandText = spName;
            command.Connection = context.Database.Connection;

            command.Parameters.AddRange(parameters);

            //Forget this if you don't have any out parameters
            command.Parameters.AddRange(outParameters);

            try
            {
                command.Connection.Open();
                var reader = await command.ExecuteReaderAsync();
                return reader.ToObjectList();//A custom method implemented below
            }
            finally
            {
                command.Connection.Close();
            }
        }
  1. Read individual values from each row into a expando object and put the list of expando objects into an array 将每行中的各个值读入expando对象,并将expando对象列表放入数组中
            public static List<object> ToObjectList(this IDataReader dataReader, bool ignoreUnmappedColumns = true)
            {
                var list = new List<object>();
                while (dataReader.Read())
                {
                    IEnumerable<string> columnsName = dataReader.GetColumnNames();//A custom method implemented below 
                    var obj = new ExpandoObject() as IDictionary<string, object>;

                    foreach (var columnName in columnsName)
                    {
                        obj.Add(columnName, dataReader[columnName]);
                    }
                    var expando = (ExpandoObject)obj;

                    list.Add(expando);
                }

                return list;
            }
  1. Get the list of columns by using the reader.GetSchemaTable() method 使用reader.GetSchemaTable()方法获取列的列表
           public static IEnumerable<string> GetColumnNames(this IDataReader reader)
                {
                    var schemaTable = reader.GetSchemaTable();
                    return schemaTable == null
                        ? Enumerable.Empty<string>()
                        : schemaTable.Rows.OfType<DataRow>().Select(row => row["ColumnName"].ToString());
                }

Usage 用法

 var results =
                  await
                      StandaloneFunctions.GetAnonymousResults(_unitOfWork, "spFind",
                          outputParameters,parameters);

In my case, I happened to use SPs but this should work with queries. 在我的情况下,我碰巧使用SP但这应该适用于查询。 All you have to do is replace the command with the following ( and remove all the parameter passing) 您所要做的就是用以下代码替换命令(并删除所有参数传递)

command.CommandType = CommandType.Text;
command.CommandText = "select * from SomeTable";

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM