Dynamic query to obtain dynamic list from Entity Framework - c#

Actually, My project have a Entity Framework and i have a list of tables each one have different columns like one table have 3 columns and another one have 10 columns. When ever i send table name to query need to get values from database as dynamically. I have used below method to get values as dynamic,
public dynamic GetTableValuesUsingAnalysisData(AnalysisQueries queryName)
{
dynamic result = null;
try
{
using (var cases = new ApiRassiEntities())
{
result = cases.Database.SqlQuery<dynamic>(sqlQuery).ToList();
}
}
return result;
}
public class AnalysisQueries
{
public string QueryName { get; set; }
}
Above method is working correctly but the results showed as object in attached image.
I have tried lot of links but nothing helped me. Please give your suggestion.
Thanks..

Related

Loop through strongly type fields Entity Framework c#

I am trying to come up with a neat solution for this problem to make it scalable. I've got a DataTable dt, which has its structure read from a database. I want to be able to correctly map this data into the correct fields using Entity Framework and allow the code to function even if columns are added or deleted.
using (Entities db = new Entities())
{
foreach (DataRow dr in dt.Rows)
{
var result = db.myTable.SingleOrDefault(e => e.Email == dr["Email"].ToString());
foreach (SourceToDestinationMapping s in mapping)
{
// want to do something like this
result[s.DestinationColumn] = dt[s.DestinationColumn];
// instead of this
result.Name = dt["Name"].ToString();
result.Address = dt["Address"].ToString();
// all field mappings
}
}
}
Is this something that is possible to do? Or do I need to make code changes every time a new column gets added/removed? If this isn't something that works then I can switch to doing something like this without Entity Framework.
Edit:
Example would be:
1, EmailAddress, Email, 1
public partial class SourceToDestinationMapping
{
public int MappingId { get; set; }
public string SourceColumn { get; set; }
public string DestinationColumn { get; set; }
public bool Active { get; set; }
}
Since Entity Framework works with objects you'd need to use reflection to get and set properties without knowing which properties you need to operate on, and it can get pretty complicated if you have many types that you need to handle. So basically examine the type of the object you're looking at, get its list of properties, and search for columns with the same name as the property (or some other convention you have) in the data table row. But again, you'll need to handle the type conversions, if the property is an int you need to get the cell value as an int etc.

How to create dynamic Linq Select Expression with anonymous objects

Am using Entity Framework to run a query on a table. However, i need to get select columns only.
class MyEvent
{
public string Name { get; set; }
public int Id { get; set; }
virtual Stage EventStage { get; set; }
..... more columns .....
}
class Stage
{
public string Name { get; set; }
public string Location { get; set; }
..... more columns .....
}
I can write an IQueryable to return these as
dbContext.MyEvents
.Select(s =>
new {
Name = s.Name,
Id = s.Id,
EventStage = new
{
Name = s.EventStage.Name,
Id = s.EventStage.Id
}
}
)
.ToList();
This works as expected, giving me just those columns am interested in.
Now, I need to construct that 'Select' call dynamically using Expression tree, something like here.
How can I achieve that? Is it feasible to construct an anynomous object, like above, via expressions?
EDIT:
The use case for me is that I have a generic dB context class which takes a list of columns as strings to be fetched. In the past, we were returning all columns, ignoring that input list. So, now I need to dynamically generate the select statement to return only the required subset of columns, which can either be done via anonymous object or a dynamically created DTO.
Thanks
Maybe you can use something like the ToDynamic method from here:
https://gist.github.com/volak/20f453de023ff75edeb8
A possible usecase for this problem:
Let the user select the columns to display and query only those selected columns, so you don't query always the whole entity from the database.
Define a strongly typed object and return that. I would avoid using a dynamic object.
Note: you can't return an anonymous object.

LINQ query a list inside a record

EDIT
Turns out EF wont map List strings to a table. So to fix it I've created a simple table with an id, a string field and a foreign Key to the Example table, then in the example table i've updated the List<> attribute to point to this table. ...I think I had a brain fart. sorry all.
I've tried the other questions but I'm still getting the same error.
I have a table with the following:
public class Example
{
public Example()
{
ExampleList = new List<string>();
}
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public List<string> ExampleList{ get; set; }
}
Now when I go to query the database, I want to return back entries that contain "imastring" in their ExampleList I'm currently using:
var test = db.Examples.Where(c => c.ExampleList.Count(z => z.Contains("imastring")) == 0).ToList();
However, this query brings back the following error:
The specified type member 'ExampleList' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.
I can't figure out whats wrong, what am i missing guys?
For clarity
I'm trying to bring back all "Example" record whos "ExampleList<>" contains the string "imastring"
You cannot store in database list of string type (or primitives). You need to create for example ExampleTable class with id and string value. Or keep whole list in one property (for example strings separated with ';') and parse given string with split. Or serialize list to json and save as string property.

ADO.NET build complex objects using DataReader

I'm trying to create a way to make an unique search into the database and build the right object for my needs. I mean, I use a SQL query that returns me a lot of rows and then I build the collections based on that database rows. E.g.:
We have a table called People and another table called Phones.
Let's suppose that this is my SQL query and will return the following below:
SELECT
P.[Id], P.[Name], PH.[PhoneNumber]
FROM
[dbo].[People] P
INNER JOIN
[dbo].[Phones] PH ON PH.[Person] = P.[Id]
And that's the results returned:
1 NICOLAS (123)123-1234
1 NICOLAS (235)235-2356
So, my class will be:
public interface IModel {
void CastFromReader(IDataReader reader);
}
public class PhoneModel : IModel {
public string PhoneNumber { get; set; }
public PhoneModel() { }
public PhoneModel(IDataReader reader) : this() {
CastFromReader(reader);
}
public void CastFromReader(IDataReader reader) {
PhoneNumber = (string) reader["PhoneNumber"];
}
}
public class PersonModel : IModel {
public int Id { get; set; }
public string Name { get; set; }
public IList<PhoneModel> Phones { get; set; }
public PersonModel() {
Phones = new List<PhoneModel>();
}
public PersonModel(IDataReader reader) : this() {
CastFromReader(reader);
}
public void CastFromReader(IDataReader reader) {
Id = Convert.ToInt32(reader["Id"]);
Name = (string) reader["Name"];
var phone = new PhoneModel();
phone.CastFromReader(reader);
Phones.Add(phone);
// or
Phones.Add(new PhoneModel {
PhoneNumber = (string) reader["PhomeNumber"]
});
}
}
This code will generate a PersonModel object with two phone numbers. That's good so far.
However, I'm struggling to make some good way to deal when I want to manage more tables with this process.
Let's suppose, then, I have a new table called Appointments. It stores the user's appointments to the schedule.
So, adding this table to the query, the result will be:
1 NICOLAS (123)123-1234 17/09/2014
1 NICOLAS (123)123-1234 19/09/2014
1 NICOLAS (123)123-1234 27/09/2014
1 NICOLAS (235)235-2356 17/09/2014
1 NICOLAS (235)235-2356 19/09/2014
1 NICOLAS (235)235-2356 17/09/2014
As you guys can see, the problem is to manage the phones and the appointments this way. Do you can think in anything that could solve this issue?
Thank you all for the opinions!
You cannot transfer your query result to strongly typed objects without first defining these objects' types. If you want to keep query data in memory, I recommend that you transfer it into objects of a previously defined type at some point.
What follows is therefore not something that I would actually recommend doing. But I want to demonstrate to you a possibility. Judge for yourself.
As I suggested in a previous comment, you can mimick strongly typed DTOs using the Dynamic Language Runtime (DLR), which has become available with .NET 4.
Here is an example for a custom DynamicObject type that provides a seemingly strongly-typed façade for a IDataReader.
using System.Data;
using System.Dynamic; // needs assembly references to System.Core & Microsoft.CSharp
using System.Linq;
public static class DataReaderExtensions
{
public static dynamic AsDynamic(this IDataReader reader)
{
return new DynamicDataReader(reader);
}
private sealed class DynamicDataReader : DynamicObject
{
public DynamicDataReader(IDataReader reader)
{
this.reader = reader;
}
private readonly IDataReader reader;
// this method gets called for late-bound member (e.g. property) access
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
int index = reader.GetOrdinal(binder.Name);
result = index >= 0 ? reader.GetValue(index) : null;
return index >= 0;
}
}
}
Then you can use it like this:
using (IDataReader reader = someSqlCommand.ExecuteReader(…))
{
dynamic current = reader.AsDynamic(); // façade representing the current record
while (reader.Read())
{
// the magic will happen in the following two lines:
int id = current.Id; // = reader.GetInt32(reader.GetOrdinal("Id"))
string name = current.Name; // = reader.GetString(reader.GetOrdinal("Name"))
…
}
}
But beware, with this implementation, all you get is a façade for the current record. If you want to keep data of several records in memory, this implementation won't help a lot. For that purpose, you could look into several further possibilities:
Use anonymous objects: cachedRecords.Add(new { current.Id, current.Name });. This is only any good if you access the cachedRecords in the same method where you build it, because the anonymous type used will not be usable outside of the method.
Cache current's data in an ExpandoObject.
If you want to manually write a data type for each combination of columns resulting from your queries, then you have a lot of work to do, and you will end up with lots of very similar, but slightly different classes that are hard to name. Note also that these data types should not be treated as something more than what they are: Data Transfer Objects (DTOs). They are not real domain objects with domain-specific behaviour; they should just contain and transport data, nothing else.
What follows are two suggestions, or ideas. I will only scratch at the surface here and not go into too many details; since you haven't asked a very specific question, I won't provide a very specific answer.
1. A better approach might be to determine what domain entity types you've got (e.g. Person, Appointment) and what domain value types you have (e.g. Phone Number), and then build an object model from that:
struct PhoneNumber { … }
partial interface Person
{
int Id { get; }
string Name { get; }
PhoneNumber PhoneNumber { get; }
}
partial interface Appointment
{
DateTime Date { get; }
Person[] Participants { get; }
}
and then have your database code map to these. If, for example, some query returns a Person Id, Person Name, Phone Number, and an Appointment Date, then each attribute will have to be put into the correct entity type, and they will have to be linked together (e.g. via Participants) correctly. Quite a bit of work. Look into LINQ to SQL, Entity Framework, NHibernate or any other ORM if you don't want to do this manually. If your database model and your domain model are too different, even these tools might not be able to make the translation.
2. If you want to hand-code your data query layer that transforms data into a domain model, you might want to set up your queries in such a way that if they return one attribute A of entity X, and entity X has other attributes B, C, and D, then the query should also return these, such that you can always build a complete domain object from the query result. For example, if a query returned a Person Id and a Person Phone Number, but not the Person Name, you could not build Person objects (as defined above) from the query because the name is missing.
This second suggestion will at least partially save you from having to define lots of very similar DTO types (one per attribute combination). This way, you can have a DTO for a Person record, another for a Phone Number record, another for an Appointment record, perhaps (if needed) another for a combination of Person and Phone Number; but you won't need to distinguish between types such as PersonWithAllAttributes, PersonWithIdButWithoutNameOrPhoneNumber, PersonWithoutIdButWithPhoneNumber, etc. You'll just have Person containing all attributes.

Linq Select * from Table ExecuteQuery

First let me start by saying that I don't have a complete understanding of Linq. I am trying to dynamically query a database, The first query uses LINQ-SQL which works fine, but the second dynamic call is what fails in run time
public void getTables()
{
foreach (var c in dc.GetTable<TableListing>())
{
List<TableData> res = tableBrowse(c.TableName);
}
}
public List<TableData> tableBrowse(string tablename)
{
string sql = "Select * from " + tablename;
var results = dc.ExecuteQuery<TableData>(sql);
return results.ToList();
}
public class TableData
{
public int Time { get; set; }
public string Value { get; set; }
}
I query the "master table" and this retrieves a list of tables to query. They all have the same structure, as defined in the class TableData. I get a runtime error about Specified cast is not valid. I'm not really looking for code as much as I am looking for what I am doing wrong and how to fix it. Thanks.
You might try decorating your class properties with ColumnAttributes, specifying the column name and type so that LINQ to SQL knows how to do the version of the column data to the properties. You may also need to set other attribute properties to make it work correctly. I would also specify the column names in the SQL instead of using *. Put the column names in the same order as your properties appear in the class as I believe that it processes the result values in the same order as the properties are defined. Not sure it this will work or not, but essentially you're recreating what the designer would do for you.
public List<TableData> tableBrowse(string tablename)
{
string sql = "Select [time], [value] from " + tablename;
var results = dc.ExecuteQuery<TableData>(sql);
return results.ToList();
}
public class TableData
{
[Column( Name="Time", DbType="DateTime NOT NULL", ... )]
public int Time { get; set; }
[Column( Name="Value", DbType="VARCHAR(255) NOT NULL", ... )]
public string Value { get; set; }
}
You aren't explicitly converting the return value from dc.ExecuteQuery<TableData>(sql) to the TableData type that you've defined. I expect that the ExecuteQuery is complaining because it doesn't know what the TableData type is.
The ExecuteQuery helper needs to return a DBML (LINQ-to-SQL generated) type as defined in your database.
But I would suggest that you don't go down this route. If you want to get records from a table, say Customers, just use content.Customers - the point of LINQ-to-SQL is that it already contains all these accessors to save you time.
Actually I found out what the problem was, I was missing a table definition. There was a third data type in one of the tables. Once I defined that table class and checked for the data type it worked fine. Sadly the compiler just didn't give that much information on just what was wrong.

Categories

Resources