Index linq result using a dictionary or similar - linq

I am using LINQ to SQL (through LINQPad) to extract some data from a MySQL database.
var res = MyTable.First();
res.Dump();
And I have 255 columns like so.
i0 | 0.01
i1 | 0.11
i2 | 4.01
...
i254 | 1.12
I would like to convert the values from the 255 columns into an array after the select. Is there a way to iterate through the value of res as a dictionary so it will be possible to make a loop like (in pseudo code):
for i in 0..254 do
array[i] = res["i" + i]

As suggested by #sloth I got it to work with reflection as so:
var type = res.GetType();
type.GetMembers().Where(s => s.Name.StartsWith("i")).Select(s => new { Name = s.Name, Value=s.GetValue(res)}).Dump();

You could use reflection the get the properties.
Example:
var res = MyTable.First();
var type = res.GetType();
for(int i=0; i<=254; i++)
array[i] = type.GetProperty("i" + i).GetValue(res);

Related

Converting Int to String using map function in pandas

dmap = {0:'Mon',1:'Tue',2:'Wed',3:'Thur',4:'Fri',5:'Sat',6:'Sun'}
df['DayOfWeek']=df['DayOfWeek'].map(dmap)
df.head()
DayOfWeek column value is Showing as NaN rather then String
I didn't understand your question exactly but i guess it has to be something like that
dmap = {0:'Mon',1:'Tue',2:'Wed',3:'Thur',4:'Fri',5:'Sat',6:'Sun'}
count = 0
df = pd.DataFrame({'DayNumber':[], 'DayOfWeek': []})
for key, value in dmap.items() :
df.loc[count] = [str(key) , value]
count = count + 1
print(df.head())

Row number in LINQ

I have a linq query like this:
var accounts =
from account in context.Accounts
from guranteer in account.Gurantors
where guranteer.GuarantorRegistryId == guranteerRegistryId
select new AccountsReport
{
recordIndex = ?
CreditRegistryId = account.CreditRegistryId,
AccountNumber = account.AccountNo,
}
I want to populate recordIndex with the value of current row number in collection returned by the LINQ. How can I get row number ?
Row number is not supported in linq-to-entities. You must first retrieve records from database without row number and then add row number by linq-to-objects. Something like:
var accounts =
(from account in context.Accounts
from guranteer in account.Gurantors
where guranteer.GuarantorRegistryId == guranteerRegistryId
select new
{
CreditRegistryId = account.CreditRegistryId,
AccountNumber = account.AccountNo,
})
.AsEnumerable() // Moving to linq-to-objects
.Select((r, i) => new AccountReport
{
RecordIndex = i,
CreditRegistryId = r.CreditRegistryId,
AccountNumber = r.AccountNo,
});
LINQ to objects has this builtin for any enumerator:
http://weblogs.asp.net/fmarguerie/archive/2008/11/10/using-the-select-linq-query-operator-with-indexes.aspx
Edit: Although IQueryable supports it too (here and here) it has been mentioned that this does unfortunately not work for LINQ to SQL/Entities.
new []{"aap", "noot", "mies"}
.Select( (element, index) => new { element, index });
Will result in:
{ { element = aap, index = 0 },
{ element = noot, index = 1 },
{ element = mies, index = 2 } }
There are other LINQ Extension methods (like .Where) with the extra index parameter overload
Try using let like this:
int[] ints = new[] { 1, 2, 3, 4, 5 };
int counter = 0;
var result = from i in ints
where i % 2 == 0
let number = ++counter
select new { I = i, Number = number };
foreach (var r in result)
{
Console.WriteLine(r.Number + ": " + r.I);
}
I cannot test it with actual LINQ to SQL or Entity Framework right now. Note that the above code will retain the value of the counter between multiple executions of the query.
If this is not supported with your specific provider you can always foreach (thus forcing the execution of the query) and assign the number manually in code.
Because the query inside the question filters by a single id, I think the answers given wont help out. Ofcourse you can do it all in memory client side, but depending how large the dataset is, and whether network is involved, this could be an issue.
If you need a SQL ROW_NUMBER [..] OVER [..] equivalent, the only way I know is to create a view in your SQL server and query against that.
This Tested and Works:
Amend your code as follows:
int counter = 0;
var accounts =
from account in context.Accounts
from guranteer in account.Gurantors
where guranteer.GuarantorRegistryId == guranteerRegistryId
select new AccountsReport
{
recordIndex = counter++
CreditRegistryId = account.CreditRegistryId,
AccountNumber = account.AccountNo,
}
Hope this helps.. Though its late:)

Linq static method error

I have created following function to get dates difference:
public static double MonthsDifference(DateTime dtStart, DateTime dtNow)
{
DateTime start = dtStart;
DateTime end = dtNow;
int compMonth = (end.Month + end.Year * 12) - (start.Month + start.Year * 12);
double daysInEndMonth = (end - end.AddMonths(1)).Days;
double months = compMonth + (start.Day - end.Day) / daysInEndMonth;
return months;
}
I am using it in my LINQ query
var query = from c in context.AccountOwners.Where( MonthsDifference(p.Account.StateChangeDate,DateTime.Now) < 4 )
select c;
return query.Count();
but it is giving error:
LINQ to Entities does not recognize the method 'Double MonthsDifference(System.DateTime, System.DateTime)' method, and this method cannot be translated into a store expression.
Please suggest solution
The MonthsDifference function cannot be mapped to SQL, which is why you are getting this error. You need to either rewrite the query expression without any calls to your own methods to do what you want (which may be impossible -- I don't know exactly which native database functions LINQ to Sql supports), or fetch the result set and do the filtering locally.
The latter approach would go like this:
var count = context.AccountOwners.ToArray()
.Count(o => MonthsDifference(p.Account.StateChangeDate,DateTime.Now) < 4);
If you want to do this in the Linq then you need to inline this method so that Linq2Sql can translate it into sql.
So I think you'll need something like:
var start = DateTime.Now;
var query = from c in context.AccountOwners
let accountDate = c.Account.StateChangeDate
let diff = (start.Month + start.Year * 12) - (accountDate.Month + accountDate.Year * 12) + ...
where diff < 4
select c;
return query.Count();
Linked to Months difference between dates
In LINQ to Entities you can use Entity functions:
using System.Data.Objects;
var query = from c in context.AccountOwners.Where(EntityFunctions.DiffMonths(
p.Account.StateChangeDate,DateTime.Now) < 4 )
select c;
return query.Count();

LINQ: Field is not a reference field

I've got a list of IQueryable. I'm trying to split this list into an array of IQueryable matching on a certain field (say fieldnum) in the first list...
for example, if fieldnum == 1, it should go into array[1]. I'm using Where() to filter based on this field, it looks something like this:
var allItems = FillListofMyObjects();
var Filtered = new List<IQueryable<myObject>(MAX+1);
for (var i = 1; i <= MAX; i++)
{
var sublist = allItems.Where(e => e.fieldnum == i);
if (sublist.Count() == 0) continue;
Filtered[i] = sublist;
}
however, I'm getting the error Field "t1.fieldnum" is not a reference field on the if line. stepping through the debugger shows the error actually occurs on the line before (the Where() method) but either way, I don't know what I'm doing wrong.
I'm farily new to LINQ so if I'm doing this all wrong please let me know, thanks!
Why don't you just use ToLookup?
var allItemsPerFieldNum = allItems.ToLookup(e => e.fieldnum);
Do you need to reevaluate the expression every time you get the values?
Why not use a dictionary?
var dictionary = allItems.ToDictionar(y => y.fieldnum);

Linq to NHibernate, Order by Rand()?

I'm using Linq To Nhibernate, and with a HQL statement I can do something like this:
string hql = "from Entity e order by rand()";
Andi t will be ordered so random, and I'd link to know How can I do the same statement with Linq to Nhibernate ?
I try this:
var result = from e in Session.Linq<Entity>
orderby new Random().Next(0,100)
select e;
but it throws a exception and doesn't work...
is there any other way or solution?
Thanks
Cheers
I guess Linq to NHibernate is unable to convert the Random.Next call to SQL...
An option would be to sort the results after you retrieve them from the DB :
var rand = new Random();
var query = from e in Session.Linq<Entity>
select e;
var result = from e in query.AsEnumerable()
orderby rand.Next(0,100)
select e;
Note that you need to use a single instance of Random, because the seed is based on the current number of ticks ; if you create several instances of Random with very short interval, they will have the same seed, and generate the same sequence.
Anyway, sorting a collection based on a random number is not such a good idea, because the sort won't be stable and could theoretically last forever. If you need to shuffle the results, you can use the Fisher-Yates algorithm :
var result = Session.Linq<Entity>().ToArray();
var rand = new Random();
for(int i = result.Length - 1; i > 0; i--)
{
int swapIndex = rand.Next(i + 1);
var tmp = result[i];
result[i] = result[swapIndex];
result[swapIndex] = tmp;
}

Resources