I am still a beginner at writing C# and SQL and was wondering if someone could help me with this basic question. I have looked all over the internet and am still stuck.
I am trying to write a WCF service to access my database. I only need one method:
public PathDto GetPath(string src, string trg)
{
using (var context = new PathsEntities())
{
var p = (
from a
in context.src
where a.Target = trg
select a).Distance, Path;
}
}
where the parameter src is the table name, and the string trg is the entity's primary key.
Visual studio gives me the error: ...pathsService does not contain a definition for src because it is trying to look up the table "src" and not the string contained in the variable.
How can I use my parameter in the lookup statement?
I am going to assume you are using DbContext EF5.0 stuff
public PathDto GetPath(string tableType, string id)
{
using (var context = new PathsEntities())
{
var type = Type.GetType(tableType);
var p = context.Set(type).Find(id);
return (PathDto)p;
}
}
Seems you DON'T use EF 5.0 and have only got EF 4.0 and are using ObjectContext. Try this...no idea if it works since I don't really use EF 4.0. Alternatively download EF 5.0
public PathDto GetPath(string tableType, string id)
{
using (var context = new PathsEntities())
{
var type = Type.GetType(tableType);
var p = context.GetObjectByKey(new EntityKey(tableType, "id", id));
return (PathDto)p;
}
}
Related
I've this code and everything works just fine.
using (var db = new ApplicationDbContext())
{
md = db.Modles.ToList();
}
My question is that I have a parameter called M and that is the name of a Model I've created, so it can be dynamic.
Is there a way to do something like this:
var M = "Modles"; // or M = "Modles2"
using (var db = new ApplicationDbContext())
{
md = db[M].ToList();
}
I've tried Entity Framework Get Table By Name and Entity Framework get table by variable name but without any luck.
Can this be done?
The solution on second link you provided actually doesn't work because it's missing a simple step: The method Set on DbContext is a generic method, so you cannot simply invoke it without telling the type, either at compile time or at least at runtime. Since you want it to be called dynamically, runtime resolution is the option you're left with. The following example should work:
var entityNs = "myentities";
var table = "Model";
var entityType = Type.GetType($"{entityNs}.{table}");
var methodInfo = typeof(ApplicationDbContext).GetMethod("Set");
var generic = methodInfo.MakeGenericMethod(entityType);
dynamic dbSet = generic.Invoke(myContext, null);
var list = dbSet.GetList();
Reference: How do I use reflection to call a generic method?
I try to find entity by its id in liteDb. But the wrong entity returns as a result (with another id).
It's reproduced only on one entity for one client (other clients works good).
I use LiteDB 4.1.2.0 in my program, also I tried to find the entity in LiteDBViewer (4.1.0.0).
var id = Guid.Parse("9fe943d3-97d4-4301-8279-eca89b4209ee");
var order = dbOrders.FindById(id);
//dbOrders is LiteCollection<Order>
I expect that liteDb will return entity with my id (9fe943d3-97d4-4301-8279-eca89b4209ee), but the actual output entity with id = 2aba5886-ca30-4d67-9cf8-558441ef5eb6.
The result of liteDbViewer: https://i.ibb.co/WntgmZK/2019-08-16-1230.png
Welcome to the community!
Based on the information you provided, you could try the following:
var id = Guid.Parse("9fe943d3-97d4-4301-8279-eca89b4209ee");
var order = dbOrders.FindOne(o => o.Id == id);
Make sure that the attribute "Id" in column "Orders" is of type "guid". If it isn't, either make it one, or use id.ToString() if it's of string type.
https://github.com/mbdavid/LiteDB/wiki/Queries
EDIT:
static void Main(string[] args)
{
// Open database (or create if not exits)
using (var db = new LiteDatabase(#"MyData.db"))
{
// Get user collection
var users = db.GetCollection<User>("users");
var id = Guid.Parse("8dd0997e-42b1-432d-820e-4637dd08fa2e");
//var userById = users.FindOne(x => x.Id == id);
var userById = users.FindById(id);
if (id != userById.Id)
Console.WriteLine("Error!");
}
}
I'm not sure where the problem could be. The above code works as expected. The only difference is that you're using LiteCollection<Order> instead of GetCollection<Order>. Could you share its structure in your main post?
I am currently having a text index in my data. I am performing a regex search and I want to make sure that the correct index is used. In the mongo shell I just used explain but how could I use explain in the C# driver?
Here's how I perform my query:
public async Task<IEnumerable<GridFSFileInfo>> Find(string fileName)
{
var filter = Builders<GridFSFileInfo>.Filter.Regex(x => x.Filename, $"/.*{fileName}.*/i");
var options = new FindOptions
{
Modifiers = new BsonDocument("$hint", "filename_text")
};
var result = new List<GridFSFileInfo>();
using (var cursor = await Collection.Find(filter, options).ToCursorAsync())
{
while (await cursor.MoveNextAsync())
{
var batch = cursor.Current;
result.AddRange(batch);
}
}
return result;
}
Is there something like Collection.Find(filter, options).Explain() that returns a string or something? I searched on the web and found this: Is there an "Explain Query" for MongoDB Linq? However is seems there is no Explain method...
The modern mongo c# drivers support only one way to configure $explain. You can do it via FindOptions.Modifiers in the same was as you configured $hint above.
var options = new FindOptions
{
Modifiers = new BsonDocument
{
{ "$hint", "filename_text" },
{ "$explain", 1 }
}
};
var cursor = coll.Find(filter, options).As<BsonDocument>().ToCursor();
Pay attention, since $explain completely changes the server response, you should change your output type to BsonDocument(or a type with fields that matches to what explain returns) via As (if it's already not BsonDocument)
I am using asp.net mvc, dapper and MySql stored procedures for my web app.
So far, for each page I have 1-3 stored procedures calls.
I recently found out my hosting only provides 10 parallel connections and so I want to combine my calls into one per page.
I already made the necessary stored procedures in the database, but my problem is using dapper in generic way to get the procedures results.
What I want is to make a generic function that will get:
1) Stored Procedure name.
2) List of types the stored procedure returns. And for each type if it is Single/ToList.
The generic function should result a list of variablese that are the results from the stored procedure.
The example in dapper page shows how to make a non-generic QueryMultiple call:
var sql =
#"
select * from Customers where CustomerId = #id
select * from Orders where CustomerId = #id
select * from Returns where CustomerId = #id";
using (var multi = connection.QueryMultiple(sql, new {id=selectedId}))
{
var customer = multi.Read<Customer>().Single();
var orders = multi.Read<Order>().ToList();
var returns = multi.Read<Return>().ToList();
...
}
Basicly, what I want is to insert the Customer,Order,Return types into a dictionary that will state each of them to be Single or ToList, and then do something like:
var result = new List<dynamic>();
var sql =
#"
select * from Customers where CustomerId = #id
select * from Orders where CustomerId = #id
select * from Returns where CustomerId = #id";
using (var multi = connection.QueryMultiple(sql, new {id=selectedId}))
{
foreach(var item in dictionary)
{
if (item.Value.equals("Single"))
result.Add(multi.Read<item.Key>().Single());
else if (item.Value.equals("ToList"))
result.Add(multi.Read<item.Key>().ToList());
}
}
return result;
My problem is, visual studio says:
The type or namespace name 'item' could not be found
Pointing at 'item' in: multi.Read()
What am I doing wrong?
Is there a better way to implement a generic function that uses dapper's QueryMultiple?
It's an old topic though but thought it might help others. In that case you can use below code to make it work. Pass type in Read function as parameter. You can return dynamic. Using Expando Object you can generate properties dynamically.
I would prefer to create object like below and pass list of object to function which will generate dynamic return type for you.
public class MapItem
{
public Type Type { get; private set; }
public DataRetriveTypeEnum DataRetriveType { get; private set; }
public string PropertyName { get; private set; }
public MapItem(Type type, DataRetriveTypeEnum dataRetriveType, string propertyName)
{
Type = type;
DataRetriveType = dataRetriveType;
PropertyName = propertyName;
}
}
//And then make a reusable function like below
public async Task<dynamic> ExecuteQueryMultipleAsync(IDbConnection con, string spName, object param = null,IEnumerable<MapItem> mapItems = null)
{
var data = new ExpandoObject();
using (var multi = await con.QueryMultipleAsync(spName,param, commandType:CommandType.StoredProcedure))
{
if (mapItems == null) return data;
foreach (var item in mapItems)
{
if (item.DataRetriveType == DataRetriveTypeEnum.FirstOrDefault)
{
var singleItem = multi.Read(item.Type).FirstOrDefault();
((IDictionary<string, object>) data).Add(item.PropertyName, singleItem);
}
if (item.DataRetriveType == DataRetriveTypeEnum.List)
{
var listItem = multi.Read(item.Type).ToList();
((IDictionary<string, object>)data).Add(item.PropertyName, listItem);
}
}
return data;
}
}
Below how you call the above method:
var mapItems = new List<MapItem>()
{
new MapItem(typeof(YourObject1), DataRetriveTypeEnum.FirstOrDefault, "Object1"),
new MapItem(typeof(YourObject2), DataRetriveTypeEnum.List, "Object2")
};
var response = await ExecuteQueryMultipleAsync(name, request, mapItems);
var object1 = response.Result.Object1;
var listOfObject2 = ((List<dynamic>)response.Result.Object2).Cast<YourObject2>();
Hope this helps.
Cheers
I think an alternative approach could be instead of QueryMultiple() method, you can make use of
IDbConnection.ExecuteReader()
extension method from Dapper.SqlMapper which returns IDataReader and you can loop through it and get the result sets by reader.NextResult() and map them to your object.
So I'm attempting to dynamically load my domain data service where the table name is the string ... Here's what I've got so far: Normally I'd load like this:
theDomainDataService.Load(theDomainDataService.getUsersQuery());
so I'm trying to automate which entity is loaded by the string name.
String theVariableEntityName = "Users";
Type t = theDomainDataService.GetType();
MethodInfo stuff = t.GetMethod("Get" + theVariableEntityName + "Query");
var theQuery = stuff.Invoke(theDomainDataService, null);
theDomainDataService.Load((EntityQuery<MySite.Web.Models.User>)theQuery);
---------------------------------------------------------^ Problem
This is in fact loading my domainDataService correctly, but what I need is a dynamic way to infer the type of the EntityQuery (without explicitly declaring it's going to be a User), because in fact it could be anything.
I have tried this from the DomainDataService Class with no luck, it isn't finding method's "Set" or "Entry".
public List<object> void PopulateEntity(string theEntityName)
{
Type theEntity = Type.GetType("MySiteMaintenance.Web.Models." + theEntityName);
using (var db = new DatingEntities())
{
IQueryable query = db.Set(theEntity);
foreach (var item in query)
{
var entry = db.Entry(item);
}
}
}
Remember, all I need is a populated entity (when all I have is the name of the entity) populated Client side... so I can say
DomainServiceClass theClass = new DomainServiceClass();
theClass.Load(theClass.GetEntityNameQuery());
so I can reference the appropriately loaded entity with...
theClass.Entity (users... questions, etc..)
I'm still not sure I follow, but...
I have a Post entity in my Sandbox namespace which I get from my DbContext instance using the entity type name in a string to start with...
// Get my entity type (if in same assembly, else you'll have to specify)
Type postType = Type.GetType("Sandbox.Post");
using (var db = new StackOverflowEntities()) {
// not required
db.Configuration.ProxyCreationEnabled = false;
IQueryable query = db.Set(postType);
foreach (var item in query) {
DbEntityEntry entry = db.Entry(item);
}
}
Which results in retrieving any DbSet based on a Entity type string. Below a breakpoint in the item foreach loop - revealing the values.