4

I am developing a report viewer as ap.net web api application. SO I need an entity framework dynamic query result.

public IEnumerable<dynamic> MyQuery()
{
    const string queryString = " SELECT ..... " ; // this is my complex sql query
    var result = context.Database.SqlQuery<dynamic>(queryString).ToList();
    return result;
}

My sql query returns any type of object like below:

(Name, Total)

(Name, Total, Category)
(Name, TOtal, CityOnoTotal, CityTwoTotal)

So I want to use this result in my asp.net web api action method. Query runs and gets some results.

I used to see response on Postman like this.

enter image description here

My query response properties are lose.

6
  • Did you tried to send back object? (just curious for the result). Maybe it makes sense to revork an dynamic to something like Dictionary<string, object>? Commented Aug 13, 2017 at 9:13
  • No, how can I get dynamic values from in Dictionary? Can u explain more clear wit code? Commented Aug 13, 2017 at 9:21
  • @bookmarker did you try to return jsonresult by using Json.Net serialization like JsonConvert.SerializeObject(result) Commented Aug 13, 2017 at 9:46
  • Yes I used it but sql query result creates empty objects. So the result is like that. Commented Aug 13, 2017 at 9:52
  • @bookmarker I searched a bit and it seems you can not use EF SqlQuery with unknown type, this link might help you stackoverflow.com/a/25497376/8175473 Commented Aug 13, 2017 at 9:58

2 Answers 2

2

This I suppose wouldn't work, because EF is not returning properties in the dynamic object at all, for explained case.

It works other way around, First EF Takes all properties of provided Generic Type attribute, Then it tries to map properties to SQL request results.

So if you don't know what is the list of fields will be as result EF wouldn't generate it for you.

First solution will be to parse select list to define the fields and generate class dynamicaly. Check how to create dynamic class discussion. Than you can do something like

var dType = MyTypeBuilder.CompileResultType("sample", new Dictionary<string, Type>
{
    { "Id", typeof(int) }
});
var db = new Model1().Database;
var sql = db.GetType().GetMethods().Where(m => m.Name == "SqlQuery" && m.IsGenericMethod);
var gen = sql.First().MakeGenericMethod(dType);

var result = gen.Invoke(db, new object[] { "[Your SQL]", new object[0] });
var ie = (result as IEnumerable<object>);

that is really complex, but works

Second - you can do classic ADO SQLCommand using context.Database.Connection and parse results

Third way to solve the problem is to Return XML from SQL, if possible.

var query = db.SqlQuery<string>("[Your SQL] for XML PATH('item'), root('root')").First();

that will return all data in XML format Like:

<root>
    <item>
        <Id>5</Id>
        ...
    </item>
    <item>
        <Id>6</Id>
        ...
    </item>
</root>
Sign up to request clarification or add additional context in comments.

5 Comments

So I could parse DataRows to an object as dynamically. But how?
Or generate class dynamically, or call SQLCmmand via ADO and parse DataTable
check also a possibility to use XML result from SQL
Forth: Return JSON from SQL var query = db.SqlQuery<string>("[Your SQL] for json path").First();
@Shady good point. Just don't forget to mention the version, I suppose SQL Server starting with 2016
-1

Maybe just return a string and parse it when received. For example:

SELECT 
CONVERT(NVARCHAR(MAX), Name) + '|' + CONVERT(NVARCHAR(MAX), Total) + '|' + CONVERT(NVARCHAR(MAX), Category)
FROM TABLE_NAME

Then, in the front end:

string[] fields  = Results.Split('|');

You'd then need to the convert the elements to int, boolean etc.

1 Comment

No. I'm sure they're not going to change each query to accommodate splitting. Also, what if strings contain "|"? And what is Results? What if there are multiple records? What if they do want typed data in the reports?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.