Set value array with a query - arrays

I want to set this Array with the result of ths Query but I can't. How do I do it ?
String[] q = (from p in MDB.aspnet_Memberships
where p.aspnet_User.aspnet_UsersInRoles.Single().aspnet_Role.RoleName.ToString() == GroupDDL.SelectedItem.ToString()
select new{p.UserId }).ToArray();
Exception :
Cannot implicitly convert type 'AnonymousType#1[]' to 'string[]'

You're selecting a new anonymous object by using the braces. When you do "select new { p.UserID }", the compiler creates a brand new object type. You just want the userID's themselves, not a new object wrapping them up. Try just
select p.UserId).ToArray();
as your select clause.

Related

Dapper & Multi Column To Property Mapping Is It Possible?

I have a project that I am using Dapper. I have a stored procedure that returns a single row with 2 columns.
var result = connection.Query("sp_Match_Get1Row2Columns", p, commandType: CommandType.StoredProcedure);
What I am wondering is that is there a way rather then create a class to auto map to - can I map those two columns to individual parameters ?
Something like..
var dataA = result.Column1 .....
Thanks
Value-tuples might be useful in this scenario; something like:
(var id, var name) = connection.QuerySingle<(int, string)>(
"sp_Match_Get1Row2Columns", p, commandType: CommandType.StoredProcedure);
// "id" and "name" should now be declared and initialized
should work

Dapper Results(Dapper Row) with Bracket Notation

According to the Dapper documentation, you can get a dynamic list back from dapper using below code :
var rows = connection.Query("select 1 A, 2 B union all select 3, 4");
((int)rows[0].A)
.IsEqualTo(1);
((int)rows[0].B)
.IsEqualTo(2);
((int)rows[1].A)
.IsEqualTo(3);
((int)rows[1].B)
.IsEqualTo(4);
What is however the use of dynamic if you have to know the field names and datatypes of the fields.
If I have :
var result = Db.Query("Select * from Data.Tables");
I want to be able to do the following :
Get a list of the field names and data types returned.
Iterate over it using the field names and get back data in the following ways :
result.Fields
["Id", "Description"]
result[0].values
[1, "This is the description"]
This would allow me to get
result[0].["Id"].Value
which will give results 1 and be of type e.g. Int 32
result[0].["Id"].Type --- what datattype is the value returned
result[0].["Description"]
which will give results "This is the description" and will be of type string.
I see there is a results[0].table which has a dapperrow object with an array of the fieldnames and there is also a result.values which is an object[2] with the values in it, but it can not be accessed. If I add a watch to the drilled down column name, I can get the id. The automatically created watch is :
(new System.Collections.Generic.Mscorlib_CollectionDebugView<Dapper.SqlMapper.DapperRow>(result as System.Collections.Generic.List<Dapper.SqlMapper.DapperRow>)).Items[0].table.FieldNames[0] "Id" string
So I should be able to get result[0].Items[0].table.FieldNames[0] and get "Id" back.
You can cast each row to an IDictionary<string, object>, which should provide access to the names and the values. We don't explicitly track the types currently - we simply don't have a need to. If that isn't enough, consider using the dapper method that returns an IDataReader - this will provide access to the raw data, while still allowing convenient call / parameterization syntax.
For example:
var rows = ...
foreach(IDictionary<string, object> row in rows) {
Console.WriteLine("row:");
foreach(var pair in row) {
Console.WriteLine(" {0} = {1}", pair.Key, pair.Value);
}
}

Using contains to match two fields

I have a database table which has a bunch of fields including one called Type and another called Code. I also have a list of Type and Code pairs that are encapsulated in a class. Something like this:
public class TypeAndCode
{
public byte Type { get; set; }
public int Code { get; set; }
// overrides for Equals and GetHashCode to compare if Type and Code are equal
}
Now what I need to do is select from the table only those entries who type AND code match an entry in my collection. So, for example, I tried something like this:
var query = myTable.Where(a => myTCList.Contains(new TypeAndCode() { Type = a.Type, Code = a.Code }).ToList();
But it'll give me a NotSupportedException:
Unable to create a constant value of type 'TypeAndCode'. Only primitive types
or enumeration types are supported in this context.
Is there a way to make this work so that I can retrieve from the database only those entries that have a Code and Type that match my list of Code and Type? I'm trying to avoid having to retrieve all the entries (it's a big table) and match them in memory.
I'm aware that I could try something like
var query = myTable.Where(a => listOfTypes.Contains(a.Type) && listOfCodes.Contains(a.Codes))
But that will make some spurious matches where the type and code are from different pairs in my original list.
You can use Any instead:
var query = myTable
.Where(a => myTCList.Any(t => t.Type == a.Type && t.Code == a.Code ))
.ToList();
You should be able to just do this manually without the overloaded methods from your class:
myTCList.Any(x => x.Type == a.Type && x.Code == a.Code)
My ulitmate solution here, in case anybody else encounters a similar problem, was to set up a temporary table that I could write the pairs I wanted to match to which I could them join with the database table. After doing the join and materializing the results, you can delete the temporary table.
Something like:
ctx.myTempTable = (from pair in mypairs
select new myTempTable() { Type = pair.Type, Code = pair.Code }).ToList();
ctx.SaveChanges();
var query = from q in myTable
join t in ctx.myTempTable
on new { q.Type, q.Code } equals new { t.Code, t.Type }
select q;
The whole thing is in a try/catch/finally block with the finally block used to clear up the temporary table(s)

what's the catch (select new in LINQ vs simply filling the object)

can someone please explain the difference between these 2 pieces of code:
var temp = (from c in Context.SomeTable
select new SomeObject { name=c.Name, created = c.Created}).ToList();
and this :
var temp = (from c in Context.SomeTable select c);
foreach(SomeTable t in temp)
{
SomeObject so = new SomeObject();
so.name = t.Name;
so.created = t.Created;
}
SomeTable.Created is a nullable datetime type field in the database.
While the first piece throws an exception:
Sqldatetime overflow. must be between 1/1/1753 12:00:00 am and 12/31/9999 11:59:59 pm.
the second one works.
Thank You!
In the first code no c will be read from SomeTable or instance of SomeObject will be created until something enumerates temp.
The second this enumeration takes place.
Therefore I would expect there is an issue with the validity of Context.SomeTable when temp is enumerated in the first case.
Test this by changing the first block to:
var temp = (from c in Context.SomeTable
select new SomeObject { name=c.Name, created = c.Created}
).ToList();
which forces immediate enumeration.

Custom query with Castle ActiveRecord

I'm trying to figure out how to execute a custom query with Castle ActiveRecord.
I was able to run simple query that returns my entity, but what I really need is the query like that below (with custom field set):
select count(1) as cnt, data from workstationevent where serverdatetime >= :minDate and serverdatetime < :maxDate and userId = 1 group by data having count(1) > :threshold
Thanks!
In this case what you want is HqlBasedQuery. Your query will be a projection, so what you'll get back will be an ArrayList of tuples containing the results (the content of each element of the ArrayList will depend on the query, but for more than one value will be object[]).
HqlBasedQuery query = new HqlBasedQuery(typeof(WorkStationEvent),
"select count(1) as cnt, data from workstationevent where
serverdatetime >= :minDate and serverdatetime < :maxDate
and userId = 1 group by data having count(1) > :threshold");
var results =
(ArrayList)ActiveRecordMediator.ExecuteQuery(query);
foreach(object[] tuple in results)
{
int count = (int)tuple[0]; // = cnt
string data = (string)tuple[1]; // = data (assuming this is a string)
// do something here with these results
}
You can create an anonymous type to hold the results in a more meaningful fashion. For example:
var results = from summary in
(ArrayList)ActiveRecordMediator.ExecuteQuery(query)
select new {
Count = (int)summary[0], Data = (string)summary[1]
};
Now results will contain a collection of anonymous types with properties Count and Data. Or indeed you could create your own summary type and populate it out this way too.
ActiveRecord also has the ProjectionQuery which does much the same thing but can only return actual mapped properties rather than aggregates or functions as you can with HQL.
Be aware though, if you're using ActiveRecord 1.0.3 (RC3) as I was, this will result in a runtime InvalidCastException. ActiveRecordMediator.ExecuteQuery returns an ArrayList and not a generic ICollection. So in order to make it work, just change this line:
var results = (ICollection<object[]>) ActiveRecordMediator.ExecuteQuery(query);
to
var results = (ArrayList) ActiveRecordMediator.ExecuteQuery(query);
and it should work.
Also note that using count(1) in your hql statement will make the query return an ArrayList of String instead of an ArrayList of object[] (which is what you get when using count(*).)
Just thought I'd point this out for the sake of having it all documented in one place.

Resources