Edit
To understand what i am trying to do i will give an example
Suppose you used entity framework to generate multiple tables. Now you have MyDbEntities with objects (client, user, product, singer [attributes don't matter]). Now you create a method. This method gets an object as a parameter + MyDbEntities. The object would be a client, user, product, singer. In this method you have a query that given the object would return a list of that object. I am trying to create this method but i am still trying either with linq or sql but in vain so far
Update
I tried this, it works, but not the way i want it to. to understand me check the code below.
ViewBag.ok = LibMethods.get_all(MyDbEntities, "Client"); //Params = Entity & String
this how i can my method below is my method
public static Object get_all (MyDbEntitiesce, String given_entity_type)
{
if (given_entity_type.Equals("Client"))
{
var get_all = from clt in ce.Client
select clt;
return get_all.ToList().First();
}
else if (given_entity_type.Equals("Product"))
{
var get_all = from pdt in ce.Product
select pdt;
return get_all.ToList().First();
}
return null;
}
As you can see this method checks the object given and creates and returns a list of objects of that given_entity_type. here i return the first element just because i am doing this for tests.
now suppose that i add a new object to MyDbEntities & call it Developer i would have to update that method but i don't want to do that i want something generic that would work on any object i give it that exists in MyDbEntities. that's what i mean by generic/dynamic.
Would the OfType query be what you want? I'm not sure I clearly understand your question, but this query will filter the list of objects by the given type.
Although I do not understand what your ultimate goal is, I would suggest that you look into DbSet.Set() method:
You can then use it like this Context.Set<Singer>() or Context.Set<Client>() depending on your target table.
That is the most generic you can get. Try showing more Code to make your scenario more clear.
Related
Is it possible to return a result set from the database without knowing the schema in advanced?
I'm exposing the ability for the client to pass parameters to a stored procedure via API:
[Route("TheRequest")]
public object Get([FromUri] TheRequest request)
This will then return:
_repository.Database.SqlQuery<object>(request.ToSqlString()); //execute sql against a stored procedure, passing in the required parameters to it
When attempting to do this, I believe that the controller doesn't know how to serialize the object returned. This is what postman returns:
Is it possible to return a Json serialized object response from the database without knowing the object schema?
Is it possible to return a result set from the database without knowing the schema in advanced?
In regards to just EF, the answer is not really. EF was designed for you to know the schema in advance. So you can still use DAO off of the ContextDb.Database but there isn't much point to using EF you you do that.
Now if the question was, can I generically typed instance from EF then sure, no problem:
var result = DbContext.Set<T>().FirstOrDefault();
This code doesn't know what it's pulling at compile time.
Is it possible to return a Json serialized object response from the database without knowing the object schema?
Sorta, as I mentioned before, you can't use EF as it was intended, but you could certainly do something like
public ActionResult Index(string type)
{
var entityType = Type.GetType(type);
// reflection
var methods = typeof(ContextDb).GetMethods("Set");
// Not tested, but something like the following
// Find the Generic Version
var method = methods.Where(m => m.IsGenericMethod).FirstOrDefault();
// Make the method info for the typed method
var methodInfo = method.MakeGenericMethod(entityType);
// Invoke method, cast as needed, get value
var result = (methodInfo.Invoke(ContextDb) as DbSet).FirstOrDefault();
return Json(result);
}
I am using Rally Api to fetch some details, need to add more query clauses(.and) dynamically. Tried creating a string and then adding but parse error is what I am getting. Can some one help here?
editing
storyRequest.Query = new Query("LastUpdateDate", Query.Operator.GreaterThan, "2013-08-01");
Supposing I want to keep adding .and queries to the above one dynamically based on my inputs.
For instance I want the stories for different projects, iterations and releases and the user selects them.so in that case how will I add. I tried creating a string which will have and queries based on the input but am unable to append it to the earlier one. Any approach here would be useful.
Not sure whether you are looking for solution like this. Dont have enough reputation to comment. this is an example in java
//Inside Function start
public static QueryFilter q;
private static QueryFilter setDynamicQuery(String fieldName,String Operator,String fieldValue)
{
q=new QueryFilter(fieldName, Operator, fieldValue);
return q;
}
//Inside Function end
//When calling in main method start
QueryRequest existUserStoryRequest = new QueryRequest("HierarchicalRequirement");
String existStoryFormattedIDLst="US23456!US23457!US23446";
for(String StoryFormattedID:existStoryFormattedIDLst.split("!")){
existUserStoryRequest.setQueryFilter(setDynamicQuery("FormattedID", "=", StoryFormattedID));
}
//When calling in main method end
I am trying to simplify and compact my code, and eliminate code duplication as much as possible. I have a method that queries RavenDB collections, and the query needs to adapt to the type I am going to query. This type changes according to the parameters passed to the method, and the where clause also needs to adapt.
I have a base type, AdministrativeArea, which other types derive from (Level1_AdministrativeAreas to Level5_AdministrativeAreas). Depending on the scenario, I need to query AdministrativeAreas, Level1_AdministrativeAreas, etc.
What I currently have:
private void Merge(MergeLevel currentMergeLevel, IDocumentSession currentSession)
{
(...)
IQueryable<AdministrativeArea> query;
if (currentMergeLevel == MergeLevel.Level1)
query = currentSession.Query<AdministrativeArea, AdminAreaName>()
.Where(area => !string.IsNullOrEmpty(area.NAME_0) && !string.IsNullOrEmpty(area.NAME_1));
(...)
}
Is there any way to pass in the types as a method parameter and have them applied to the query, like this:
private void Merge(MergeLevel currentMergeLevel, IDocumentSession currentSession, Type requiredType, Type indexType)
{
(...)
IQueryable<requiredType> query;
if (currentMergeLevel == MergeLevel.Level1)
query = currentSession.Query<requiredType, indexType>()
.Where(area => !string.IsNullOrEmpty(area.NAME_0) && !string.IsNullOrEmpty(area.NAME_1));
(...)
}
I have faced several problems at compile time, namely "is a variable but is used like a type", and the fact that member variables (NAME_0, NAME_1, etc.) can't be inferred because the compiler doesn't know "what's coming".
I suspect this simply can't be done; however, this has implications for code maintenance, as I'll have to create different methods for each type of query OR create one rather large method. Neither of which are too appealing, but I don't see any way around that.
A good way of filtering by type would be to include Raven-Entity-Name field in the "select" clause of an index.
Then you would be able to filter types by using EntityType field.
You can see an example of this kind of index in the built-in Raven/DocumentsByEntityName index
So, your index might look like this:
from doc in docs
let entityType = doc["#metadata"]["Raven-Entity-Name"]
where entityType.EndsWith("_AdministrativeAreas")
select new
{
EntityType = entityType,
//the rest of the fields
}
Note that this would work if you are inserting documents through existing client API (raw REST API won't add Raven-Entity-Name on it's own)
I am trying to write a wrapper function for an application.
This application will continually add entities so it would be better if we could write one generic function rather than have to carve out an exception for each item.
For certain reasons we maintain both a GUID and an int key.
When an int key gets updated, we need to update it both in the parent record the child records but since it is possible that at any given time there could be multiple child records with the same int key, we need to get a list of Guids of what we want to update.
Here is some psuedo code of what I am trying to do.
List<string> depenedents = new List<string>();
depenedents.add(table1);
depenedents.add(table2);
depenedents.add(table3);
for(item in depenedents)
{
context.set<type item>();
entities.getguid();
}
Obviously the issue here is with the for loop.
Is it possible to get a list of entities knowing only the string of the entity type? Luckily all of our entities are wrapped to a base class that has a get guid method, but I need to find a way to actually get the entities.
Any help is greatly appreciated.
Something like:
for(item in depenedents)
{
context.GetMethod("Set")
.MakeGenericType(Type.GetType(item))
.Invoke(context, new object[0]);
entities.GetType.GetMethod("GetGuid").Invoke(entities, new object[0]);
}
...should be with roughly what you need. This will invoke the correct type specialisation of the Set generic instance method. Then it will invoke the instance method called "GetGuid" on the entities object.
Or possibly:
foreach(var entity in entities)
{
entity.GetType.GetMethod("GetGuid").Invoke(entities, new object[0]);
}
You'll maybe want to do something with the values returned, but hopefully this answer will point you in the right direction!
(and clearly you could optimise this code substantially to cache reflected types and methods, or to use compiled expressions rather than Invoke() calls)
The following method works properly in my service layer:
public override IList<City> GetAll()
{
var query = from item in _tEntities
select item;
query.Load();
return _tEntities.Local;
}
but when i try to run following method, the method returns old data loaded by GetAll() method.
public override IList<City> GetAll(Func<City, bool> predicate)
{
var query = from item in _tEntities
select item;
query.Where<City>(predicate);
query.Load();
return _tEntities.Local;
}
What is the problem and how can i fix them?
How can i use local method in this sample and reload new data into local(cache)?
You are looking at the wrong problem. What you are most likely seeing is a result of the fact that when you do the first query, the local cache is empty. So it only returns the results from your query. But when you do the second, it's returning the results of your first query AND your second query.
This comes down to the fact that you are using a shared DbContext between all your methods. Local contains a cache of all records the context has retrieved, not just the most recent query.
The correct solution is to not use Local in this manner. Even better, don't use a shared context since this can lead to context cache bloat.
I'm not too sure what you are trying to achieve with a .Load method here but it seems like you want the following.
public override IList<City> GetAll(Func<City, bool> predicate)
{
return _tEntities.Where<City>(predicate).ToList();
}
query.Where<City>(predicate);
This doesn't change query. The query.Load() on the next line ignores the predicate: you're calling query.Load() and not query.Where<City>(predicate).Load(). It's as if you had written
int i = 3;
i + 1;
Console.WriteLine(i); // still prints 3
In that example, C# does not really actually allow an addition to be used as a statement, but .Where(predicate) is a method call, and method calls can be used as such, even if they return values.
This is not your only issue (see the other answers), but my guess is that this issue is the one that leads to the unexpected results you're seeing.