I'm trying to output data like this:
[[...],[...],[...],[...]]
But my query gives me this result:
[{...},{...},{...},{...}]
Here is my query:
var result = (from c in displayedCompanies
group c by new { c.CodigoDeVenta } into s
select new{
ID = Convert.ToString(i++),
s.Key.CodigoDeVenta,
TotalInv = s.Sum(x => x.Inventario)
}).ToArray();
I've tried some options like the following but it's wrong:
var result = (from c in displayedCompanies
group c by new { c.CodigoDeVenta } into s
select new [] {
ID = Convert.ToString(i++),
s.Key.CodigoDeVenta,
TotalInv = s.Sum(x => x.Inventario)
}).ToArray();
Note that the diference is the [] in select new []. I used to have a query before I implemented the "group by" that worked correctly, but after I added the group by this does not work anymore.
Thanks!
Setting aside the grouping, focusing only on the syntax, your anonymous array (new [] {...}) should be fine.
However, it appears that you're trying to assign Id = and TotalInv = which looks like a leftover from the previous revision where you were selecting an anonymous object.
So, instead, you should be able to drop the member identifiers and select just the values you want in the child arrays:
select new [] {
Convert.ToString(i++),
s.Key.CodigoDeVenta,
s.Sum(x => x.Inventario)
}
Related
The basis of this question is from this question:
Combine 2 classes with adding data and 1 table has a colllection list of the other table and wanting to use linq to display
In which I "thought" the problem was solved.
However as I added in a new object to the List, now this join query does not output it
reportData.Add(new ReportData() {ReportGroupId = 3, ReportGroupName = "Straggler", SortOrder = 3, Type = 1});
var reports = reportDefinition.GroupBy(r=>r.ReportGroupId);
var query = reportData.Join(reports, d => d.ReportGroupId, gr => gr.Key,
(r,gr) => new
{
r.ReportGroupName,
items = gr.ToList(),
r.ReportGroupId
});
Here is the dotNetFiddle https://dotnetfiddle.net/IIBFKG
Why doesn't the item that I added to the ReportData not show up? Is it the type of JOIN in Linq?
I think the linked question was not answered correctly.
Looks like all you need is a simple Group Join:
var query =
from d in reportData
join r in reportDefinition on d.ReportGroupId equals r.ReportGroupId into items
select new
{
d.ReportGroupName,
items = items.ToList(),
d.ReportGroupId
};
Here's my code:
var myStrings = (from x in db1.MyStrings.Where(x => homeStrings.Contains(x.Content))
join y in db2.MyStaticStringTranslations on x.Id equals y.id
select new MyStringModel()
{
Id = x.Id,
Original = x.Content,
Translation = y.translation
}).ToList();
And I get the error that the specified LINQ expression contains references to queries that are associated with different contexts. I know that the problem is that I try to access tables from both db1 and db2, but how do I fix this?
MyStrings is a small table
Load filtered MyStrings in memory, then join with MyStaticStringTranslations using LINQ:
// Read the small table into memory, and make a dictionary from it.
// The last step will use this dictionary for joining.
var byId = db1.MyStrings
.Where(x => homeStrings.Contains(x.Content))
.ToDictionary(s => s.Id);
// Extract the keys. We will need them to filter the big table
var ids = byId.Keys.ToList();
// Bring in only the relevant records
var myStrings = db2.MyStaticStringTranslations
.Where(y => ids.Contains(y.id))
.AsEnumerable() // Make sure the joining is done in memory
.Select(y => new {
Id = y.id
// Use y.id to look up the content from the dictionary
, Original = byId[y.id].Content
, Translation = y.translation
});
You are right that db1 and db2 can't be used in the same Linq expression. x and y have to be joined in this process and not by a Linq provider. Try this:
var x = db1.MyStrings.Where(xx => homeStrings.Contains(xx.Content)).ToEnumerable();
var y = db2.MyStaticStringTranslations.ToEnumerable();
var myStrings = (from a in x
join b in y on x.Id equals y.id
select new MyStringModel()
{
Id = x.Id,
Original = x.Content,
Translation = y.translation
}).ToList();
Refer to this answer for more details: The specified LINQ expression contains references to queries that are associated with different contexts
dasblinkenlight's answer has a better overall approach than this. In this answer I'm trying to minimize the diff against your original code.
I also faced the same problem:
"The specified LINQ expression contains references to queries that are associated with different contexts."
This is because it's not able to connect to two context at a time so i find the solution as below.
Here in this example I want to list the lottery cards with the owner name but the Table having the owner name is in another Database.So I made two context DB1Context and DB2Context.and write the code as follows:
var query = from lc in db1.LotteryCardMaster
from om in db2.OwnerMaster
where lc.IsActive == 1
select new
{
lc.CashCardID,
lc.CashCardNO,
om.PersonnelName,
lc.Status
};
AB.LottryList = new List<LotteryCardMaster>();
foreach (var result in query)
{
AB.LottryList.Add(new LotteryCardMaster()
{
CashCardID = result.CashCardID,
CashCardNO = result.CashCardNO,
PersonnelName =result.PersonnelName,
Status = result.Status
});
}
but this gives me the above error so i found the other way to perform joining on two tables from diffrent database.and that way is as below.
var query = from lc in db1.LotteryCardMaster
where lc.IsActive == 1
select new
{
lc.CashCardID,
lc.CashCardNO,
om.PersonnelName,
lc.Status
};
AB.LottryList = new List<LotteryCardMaster>();
foreach (var result in query)
{
AB.LottryList.Add(new LotteryCardMaster()
{
CashCardID = result.CashCardID,
CashCardNO = result.CashCardNO,
PersonnelName =db2.OwnerMaster.FirstOrDefault(x=>x.OwnerID== result.OwnerID).OwnerName,
Status = result.Status
});
}
I have a linq query that works when it I had a list of a single value now that I change to having a List that has several properties I need to change the where clause
So this works:
List<string> etchList = new List<string>();
etchList.Add("24");
var etchVect = (from vio in AddPlas
where etchList.Any(v => vio.Key.Formatted.Equals(v))
let firstOrDefault = vio.Shapes.FirstOrDefault()
where firstOrDefault != null
select new
{
EtchVectors = firstOrDefault.Formatted
}).ToList();
However I have a new hard coded list (which will represent incoming data:
List<ExcelViolations> excelViolations = new List<ExcelViolations>();
excelViolations.Add(new ExcelViolations
{
VioID = 24,
RuleType = "SPACING",
VioType = "Line-Line",
XCoordinate = 6132,
YCoordinate = 10031.46
});
So the NEW Linq query looks like this, but is obviously will not work as
AddPlas is a List and so using this other list of excelviolations, I wish to have it do where on each one of the properties in the excelviolations list
var etchVect = (from vio in AddPlas
where excelViolations.Any(vioId => vio.Key.Formatted.Equals(vioId))
let firstOrDefault = vio.Shapes.FirstOrDefault()
select new
{
EtchVectors = firstOrDefault.Formatted
}).ToList();
Now, since this is a list within a list, I would like to do something like add in each of the properties
so for example:
where excelViolations.VioID.Any(vioId => vio.Key.Formatted.Equals(vioId))
However that is not possible, but you see that I'm trying to access the property of VioID that is in the excelViolations and match it to the Key which is in vio list
Just change this line
where excelViolations.Any(vioId => vio.Key.Formatted.Equals(vioId))
to
where excelViolations.Any(excelVio => vio.Key.Formatted.Equals(excelVio.VioID))
then i thought it will works
I have var t from linq query with this structure:
[0] = { Type = "K", Count = 1 }
[1] = { Type = "Z", Count = 8 }
and now I want to bind it to my chart with elegance (no foreach). I try to do something like this:
series1.Points.DataBindXY(t. ????, t.????);
but I don't know how to get "first column" and "second column" of my var.
Please help
Edit:
My linq query:
var t= (from oAction in Actions
group oAction by oAction.Type.Name into g
select new { Type = g.Key, Count = g.Count() }).ToArray();
I have never worked with ASP.Net charts, so I'm not sure this will work, but I think it should:
series1.Points.DataBindXY(t.Select(x => x.Type), t.Select(x => x.Count));
This will assign a collection of Type values as the x values and collection of Count values as y values.
var t= (from oAction in Actions
group oAction by oAction.Type.Name into g
select new { Type = g.Key, Count = g.Count() }).ToArray();
All-right, so you are returning an "Anonymous" type. You can definitely access t.Type or t.Count but the catch is you can do this only inside the method where this LINQ query is defined. The scope of anonymous type is limited to the method in which it is defined. You can overcome this limitation by using "dynamic" keyword. But I haven't tried this, so can't be 100% sure.
I have the following code:
var data= from row in table.AsEnumerable()
group row by row.Field<string>("id") into g
select new { Id= g.Key };
I would like to add 1 more element to the data variable. How would I do it? (is there something like a data.Concat(1) etc
If you want to add an additional Id you can indeed concat it:
data = data.Concat( new [] { new { Id= "1" } });
This works because anonymous types that have the same fields in the same order are compiled down to the same type.
You can return the LINQ result as a List<string>.
Generic lists can Add more itens easily.
var data = (from row in table.AsEnumerable()
group row by row.Field<string>("id") into g
select new { Id = g.Key }).ToList();
data.Add(new { Id = "X" });
This way you will not need to declare another variable to hold the Enumerable with the new item (since an Enumerable is imutable and can't add new items to itself).
EDIT:
Like pointed, changing the Enumerable<T> to List<T> will put and hold all the elements on the memory, wich isn't a good performance approach.
To stay with the Enumerable<T>, you can do:
data = data.Concat(new [] { new { Id = "X" } });
Because a Enumerable<Anonymous> can be placed inside itself.
I don't know how with query syntax, but you can use Concat with a single value by creating a new array of values with a single item:
IEnumerable<int> data = GetData()
.Concat(new[] { "5" });
The problem with doing this simply is that your data is an IEnumerable<AnonymousType>, which you can't simply new up, and I don't think new anonymous types are compatible with each other. (Edit: According to BrokenGlass, they are compatible. You can try his solution instead).
If they aren't compatible, you could concat the item before your Select clause, but again, how do you create an item of that type.
The solution would probably be to select to an IEnumerable<string> first, concat, then re-select into your anonymous type:
var data = (from row in table.AsEnumerable()
group row by row.Field<string>("id") into g
select g.Key)
.Concat(new[] { "5" })
.Select(k => new { Id = key });
Or to create a new named structure for your result, and concatenate one of those:
var data = from row in table.AsEnumerable()
group row by row.Field<string>("id") into g
select new MyCustomResult() { Id = g.Key };
data = data.Concat(new MyCustomResult() { Id = "5" });
You would need to change from an anonymous type to a known type and then add that new element.
// ...
select new MyResultClass { Id = g.Key };
data.Add(new MyResultClass { Id = 4 });