suppose in an entity there are attributes id, username, age, address. Now I just want id and username and I use this code for it.
Projections enable the returning of something other than a list of entities from a query.
var proj = Projections.ProjectionList()
.Add(Projections.Property("Id"), "Id")
.Add(Projections.Property("Username"), "Username");
var list2 = DetachedCriteria.For<User>()
.Add(Expression.Eq("Username", "lachlan"))
.GetExecutableCriteria( sessionFactory.GetCurrentSession())
.SetProjection( proj )
.List();
How will I retrieve the values. In which object will these value be taken.
Unless a result transformer is used, a projection will result in a list of anonymous objects with the projected values. This would be sufficient for databinding.
For other uses, you want to set a result transformer which will create objects of a known type. The AliasToBeanTransformer will create an object of the specified type for each row, and set its properties to the row values.
If you know the type of the results, you can use the generic List<T>() method.
var proj = Projections.ProjectionList()
.Add(Projections.Property("Id"), "Id")
.Add(Projections.Property("Username"), "Username");
var list2 = DetachedCriteria.For<User>()
.Add(Expression.Eq("Username", "lachlan"))
.GetExecutableCriteria( sessionFactory.GetCurrentSession())
.SetProjection( proj )
.SetResultTransformer(Transformers.AliasToBean(typeof(Result)))
.List<Result>();
Result transformers can also be used on SQL and HQL queries.
list2 = Session.CreateSQLQuery("select Id, Username from user_table")
.SetResultTransformer(Transformers.AliasToBean(typeof(Result)))
.List<Result>();
list2 = Session.CreateQuery("select Id, Username from User")
.SetResultTransformer(Transformers.AliasToBean(typeof(Result)))
.List<Result>();
In these examples the the Result class does not need to be a mapped class, and must have the selected properties.
partial class Result
{
public int Id { get; set; }
public string Username { get; set; }
}
Related
I am still new to C# and I am struggling to find a solution to my problem. My SQL dapper query returns a table (based on my understanding though it is not really a table if it is IEnumerable unlike what I am use to working with ADO and recordsets) with three columns col1, col2, and col3 and has multiple rows. I need to loop through this query result for each row and test the values (ie, a foreach loop where I check row(0).field1=5, row(1).field1 = 5 for each row, etc) do what I need to do. This seems so basic but I all the dapper tutorials I see do not show examples for this and if they do they seem to utilize class objects rather than accessing the results directly (if thats even possible or do you have to map the results to a model?) My code is as follows:
String query = "exec dbo.storeProcedure #jsonData, #mainDocJSON, #supportingDocsJSON";
IEnumerable queryResult;
using (var connection = new SqlConnection(connectionString))
{
queryResult = connection.Query(query, new { jsonData = jsonData, mainDocJSON = mainDocJSON, supportingDocsJSON = supportingDocsJSON });
}
I also end up returning IEnumerable results from the controller this code resides in so I send it back to the user in JSON using the following.
return Ok(queryResult);
connection.Query return a IEnumerable, why dont we create a class to map the set from ? Dapper is a micro-ORM, but still... ORM.
For ex: Your table return 3 column Id, Name, CreatedDate.
// declare a class to map the result first
public class ResultHolderDto
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime CreatedDate { get; set; }
}
// query somewhere
// This will return IEnumerable<ResultHolderDto>, feel free to play around as normal
var queryResult = await connection.QueryAsync<ResultHolderDto>(query, new { jsonData = jsonData, mainDocJSON = mainDocJSON, supportingDocsJSON = supportingDocsJSON });
foreach(var item in queryResult)
{
var col1Value = queryResult.Id;
var col2Value = queryResult.Name;
var col3Value = queryResult.CreatedDate;
// Then do something with col1Value, col2Value, col3Value...
}
I had a hard time to come up with a title for this :)
I've got a WCF service hooked up to a SQL-server database. I retrieve data from the DB using ADO.NET.
On some simple operations I just retrieve from the DB and then send back a json representation of the EntityObjects i just fetched which works fine. However now I'm doing a more complex fetch with a procedure. The data retrieval works fine but the procdure itself returns more columns than the actual EntityObject (Table) has. Take this for an example:
create table Person
{
Name,
BirthDate
}
// Retrieve Persons from DB with procedure that also calculates each persons actual age!
public List<EntityObject> GetPersons()
{
var personList = new List<EntityObject>();
var dataSet = dbContext.ExceuteProcedure("GET_PERSONS_WITH_AGE", parameters);
var dataTable = dataSet.Tables["result"];
foreach (DataRow row in dataTable.Rows)
{
personList.Add( new PersonEntity
{
Name = (String)row["Name"],
BirthDate = (DateTime)row["BirthDate"],
// Here i want the actual age calculation result, but since the DB-table Person does'nt have this column,
// I can't set it.
}
}
return personList;
}
Do I need to create a CustomPersonClass for this which has this extra variable? Or can I somehow force another column into Table Person in my ADO.NET object?
Please consider that I'm novice about ADO.NET, if you see other code faults in my example (regarding methods of retrival as well) please let me know.
You may consider a DTO here, a data transfer object, this addresses the considerations of the caller/client of getPersons and will be generated as JSON back to the client. Call it PersonDTO or PersonResponse. It lives in the same class as the getPersons() method and is a public class. Change the signature to of getPersons() to List<PersonDTO> getPersons(). I would also captialize GetPersons() as it is a public method.
public class PersonDTO
{
property string Name;
property string BirthDate;
property string Age;
}
// Retrieve Persons from DB with procedure that also calculates each persons actual age!
public List<PersonDTO> getPersons()
{
var personList = new List<PersonDTO>();
var dataSet = dbContext.ExceuteProcedure("GET_PERSONS_WITH_AGE", parameters);
var dataTable = dataSet.Tables["result"];
foreach (DataRow row in dataTable.Rows)
{
personList.Add( new PersonDTO
{
Name = (String)row["Name"],
BirthDate = (DateTime)row["BirthDate"],
// Here i want the actual age calculation result, but since the DB-table Person does'nt have this column,
// I can't set it.
}
}
return personList;
}
I have data model like this:
class Hand {
public int id;
...
}
class Person {
public int id;
public string name;
public IList<Hand> hands;
...
}
To get data from database, I do this:
ICriteria criteria = databaseSession.CreateCriteria(typeof(Person));
ProjectionList projections = Projections.ProjectionList();
projections
.Add(Projections.Property("id").As("id"))
.Add(Projections.Property("name").As("name"))
.Add(Projections.Property("hands").As("hands"));
projections.Add(Projections.GroupProperty("id"));
projections.Add(Projections.Count("id"), "count");
criteria.SetProjection(projections);
criteria.SetResultTransformer(
NHibernate.Transform.Transformers.AliasToBean(typeof(PersonDTO)));
But NHibernate does not load nested objects in hands property. It just gives null.
Can anyone help me how to get nested objects filled as well (for more than one level depth). Using projections instead of query would be better for me.
Note: It would not be issue in the mapping, because when I loaded data without any projection, it worked well.
a possible solution
var query = databaseSession.CreateCriteria(typeof(Person))
.JoinAlias("hands", "hand")
.SetProjection(Projections.ProjectionList()
.Add(Projections.Property("Id"))
.Add(Projections.Property("Name"))
.Add(Projections.Property("hand.Id"))
.Add(Projections.Property("hand.Foo")))
.List<object[]>()
.GroupBy(arr => (int)arr[0])
.Select(g => new PersonDTO
{
Id = g.Key,
Name = g.First().Name,
Hands = g.Select(arr => new Hand { Id = arr[2], Foo = arr[3] }).ToList(),
});
var results = query.ToList();
Question
I'm trying to use the Dynamic Linq Sample from Microsoft with BindingList<T> objects. But it looks like the Dynamic Linq will only work with IQueryable. What's the deal here, why doesn't BindingList<T> implement IQueryable. And is there a way around this?
Background Detail: I have many data sets that I need to dynamically filter at run time. Here is an example:
BindingList<MyObject> list = new BindingList<MyObject>();
MyObject selectedObj = list.FirstOrDefault(o => o.Name == "Master P")
// then later ...
MyObject selectedObj = list.FirstOrDefault(o => o.City == "Boston")
I am trying to make these queries dynamic, so the user can choose from all properties of MyObject to use in the query.
There is an Extension method on BindingList; AsQueryable(). So you can use
list.AsQueryable();
But if you want to search on all criteria could you create a search that uses an instance of MyObject as the search criteria and then generated a result set based on the Criteria in the object using standard link.
For example:
public List<MyObject> Search(MyObject SearchCriteria)
{
BindingList<MyObject> list = new BindingList<MyObject>();
list.Add(new MyObject("Test", "Boston"));
list.Add(new MyObject("Test2", "Atlanta"));
IEnumerable<MyObject> results = list.AsEnumerable();
if (!String.IsNullOrEmpty(SearchCriteria.Name))
results = results.Where(l => l.Name.Contains(SearchCriteria.Name));
if (!String.IsNullOrEmpty(SearchCriteria.City))
results = results.Where(l => l.City.Contains(SearchCriteria.City));
return results.ToList();
}
So in the following, Results1 will have 2 results and Results 2 will have only 1.
List<MyObject> results1 = Search(new MyObject("Test", ""));
List<MyObject> results2 = Search(new MyObject("Test", "Boston"));
I used a simple structure for MyObject as an example in this:
public class MyObject
{
public MyObject(string name, string city)
{
this.Name = name;
this.City = city;
}
public string Name { get; set; }
public string City { get; set; }
}
How do I convert a list of key-value pairs (String, Object) to a list of key value pairs (string, string)?
Using LINQ, you can do something like this:
var newList = oldList.Select(kv => new KeyValuePair<string, string>(kv.Key, kv.Value.ToString())).ToList()
Of course, the ToString representation may not be exactly what you are expecting if it's some complex type, but you get the idea.
List<KeyValuePair<string, object>> list = ...
List<KeyValuePair<string, object>> castedItemsList =
list
.Select(item => new KeyValuePair<string, string>(item.Key, item.Value.ToString()))
.ToList();
If the value is of type string you can just cast it:
var result = source.Select(x => new KeyValuePair<string,string>(x.key,(string)x.value)
If the value needs to be converted you can either use .ToString() as already suggested or use a converter function. Maybe your second object is a Person class with a First and LastName Property and you want to get a full name as result:
var result = source.Select(x => new KeyValuePair<string,string>(x.key, string.Format("{0} {1}", ((Person)x.Value).FirstName, ((Person)x.Value).SecondName))
Of course you can use a method to simplify your conversion
var result = source.Select(Convert);
private KeyValuePair<string,string> Convert(KeyValuePair<string,object> pair)
{
var key = pair.Key;
var person = (Person)pair.Value;
var fullName = string.Format("{0} {1}", person.FirstName, person.LastName);
return new KeyValuePair<string,string>(key, fullName);
}
You would have to Cast those objects.