Reputation: 301
I want to convert string var to entity framework class but I don't now how. I have searched a lot but can not found anything
public JsonResult GetReports(string tbl)
{
using (Context db = new Context())
{
// *** Problem is that tbl is string and I want to Cast tbl
// to Users Class OR eny of my other Class
var result= db.Database.SqlQuery<tbl>("SELECT * FROM Users");
return Json(new { data = result});
}
}
public partial class Users
{
public int ID { get; set; }
public string Name { get; set; }
public string Family { get; set; }
public Nullable<bool> Gender { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string Email { get; set; }
public string Mobile { get; set; }
public bool Deleted { get; set; }
}
The reason of way I want to do something like that is I want to crete some dynamic method and tbl
can be any of my table names (As a string)
Upvotes: 1
Views: 1692
Reputation: 107247
Generic Approach
Given that you have strongly named classes (like Users
), there should be no reason to resort to weak or dynamic approaches.
For example, if the requirement is to build a generic repository Query capability, which DRY's up the data access code and possibly introduces common cross cutting concerns like logging, instrumentation, possibly retries, and exception handling, then you can use a generic wrapper around SqlQuery<T>
:
public async Task<IEnumerable<T>> TypedQuery<T>(string myQuery)
{
try
{
using (var db = new DbContext(ConnString))
{
return await db.Database
.SqlQuery<T>(myQuery)
.ToListAsync()
.ConfigureAwait(false);
}
}
catch (Exception ex)
{
// Log error here
// Consider if the query can be retried
// Consider whether the exception should be propogated or swallowed
// Should the return type extended to indicate success / failure
return Enumerable.Empty<T>();
}
}
Which you can invoke like so, using the generic type parameter to indicate the type of the target POCO
(Users
in this case):
var repo = new MyRepo();
var myUsers = await repo.TypedQuery<Users>("SELECT Id, Name FROM Users");
The benefit is that myUsers
is a strongly typed collection.
Dynamic Approach
In theory it is possible to use the Type
overload of SqlQuery
to answer your original question. You can either pass in a System.Type
directly, or I guess you could map some other key abstraction to the type, such as this:
private static readonly IReadOnlyDictionary<string, Type> MyTypeMap
= new Dictionary<string, Type>
{
{ "users", typeof(Users)},
{ "foo", typeof(Foo)},
... other type maps here
};
public async Task<IEnumerable<object>> WeakQuery(string someType, string someQuery)
{
Type typeOfMyClass;
if (MyTypeMap.TryGetValue(someType, out typeOfMyClass))
{
using (var db = new DbContext(ConnString))
{
return await db.Database.SqlQuery(typeOfMyClass, someQuery)
.ToListAsync()
.ConfigureAwait(false);
// The problem now is that you get an untyped DbRawSqlQuery
}
}
return Enumerable.Empty<object>();
}
The problem is though is because of the weak typing that you would need to either re-cast the result, or work with dynamic, which will make for very fragile code when used, such as :
var repo = new MyRepo();
dynamic x = await repo.WeakQuery("users", "SELECT Id, Name, Gender FROM Users");
Assert.IsNotNull(x);
Assert.IsTrue(Enumerable.First(x).Name == "Foo");
SELECT *
- instead, select all of the columns explicitly to map into the Users
class.Upvotes: 1