I have an class which contains the following properties:
public class SomeClass()
{
public Int32 ObjectId1 {get;set;}
public Int32 ObjectId2 {get;set;}
public Int32 ActiveThickeness {get;set;}
public Int32 ActiveFilterThickness {get;set;}
}
I also have 2 lists:
List<SomeClass> A
List<SomeClass> B
List A has data:
| ObjectId1 | ObjectId2 | ActiveThickness | ActiveFilterThickness |
-------------------------------------------------------------------
| 1 | 3 | 50 | 0 |
------------------------------------------------------------------
| 1 | 2 | 400 | 0 |
-------------------------------------------------------------------
| 4 | 603 | 27 | 0 |
-------------------------------------------------------------------
List B has data:
| ObjectId1 | ObjectId2 | ActiveThickness | ActiveFilterThickness |
-------------------------------------------------------------------
| 1 | 3 | 0 | 13671 |
------------------------------------------------------------------
| 1 | 2 | 0 | 572 |
-------------------------------------------------------------------
| 29 | 11 | 0 | 4283 |
-------------------------------------------------------------------
I want to merge A and B (using LINQ if possible) into List C of SomeCalss which contains data as followed:
| ObjectId1 | ObjectId2 | ActiveThickness | ActiveFilterThickness |
-------------------------------------------------------------------
| 1 | 3 | 50 | 13671 |
------------------------------------------------------------------
| 1 | 2 | 400 | 572 |
-------------------------------------------------------------------
| 29 | 11 | 0 | 4283 |
-------------------------------------------------------------------
| 4 | 603 | 27 | 0 |
-------------------------------------------------------------------
How can I achieve that?
Use GroupBy to group common objects and Sum to sum required properties
var ab = A.Concat(B).GroupBy(x => new
{
x.ObjectId1,
x.ObjectId2
});
var result = ab.Select(x => new SomeClass
{
ObjectId1 = x.Key.ObjectId1,
ObjectId2 = x.Key.ObjectId2,
ActiveFilterThickness = x.Sum(i => i.ActiveFilterThickness),
ActiveThickeness = x.Sum(i => i.ActiveThickeness)
});
See LINQ - Full Outer Join (SO).
By doing a left outer join and a right outer join, and then taking the union of those two, you should get what you're looking for.
var leftOuterJoin = from someclass1 in A
join someclass2 in B
on someclass1.ObjectID2 equals someclass2.ObjectID2
into temp
from item in temp.DefaultIfEmpty(new SomeClass(){ objectID1 = someclass1.objectID1, ... })
select new SomeClass()
{
...
};
var rightOuterJoin = from someclass2 in B
join someclass1 in A
on someclass1.ObjectID2 equals someclass2.ObjectID2
into temp
from item in temp.DefaultIfEmpty(new SomeClass(){ objectID1 = someclass1.objectID1, ... })
select new SomeClass()
{
...
};
var fullOuterJoin = leftOuterJoin.Union(rightOuterJoin);
Related
Have two tables:
Catalog
|----------|----------|-----------|
| Id | Name | CreatedBy |
|----------|----------|-----------|
| 1 | Catalog1 | 1 |
| 2 | Catalog2 | 1 |
| 3 | Catalog3 | 1 |
| 4 | Catalog4 | 2 |
|----------|----------|-----------|
TemplateOnCatalog
|------------|-----------|
| TemplateId | CatalogId |
|------------|-----------|
| 1 | 1 |
| 2 | 2 |
| 3 | 1 |
| 4 | 2 |
| 5 | 2 |
| 6 | 4 |
|------------|-----------|
Using c# and Linq, how to get a list of all the catalogs, where CreatedBy = 1, and count the number of templates in the catalog. If no templates, the count value should be 0 (or empty).
Expected result:
|------------|-------------|-------------------|
| CatalogId | CatalogName | NumberOfTemplates |
|------------|-------------|-------------------|
| 1 | Catalog1 | 2 |
| 2 | Catalog2 | 3 |
| 3 | Catalog3 | 0 |
|------------|-------------|-------------------|
I try the following, but it doesn't take catalogs without templates:
var templateCatalogs =
from templateCatalog in db.Catalog.AsNoTracking()
join totc in db.TemplateOnCatalog
on templateCatalog.Id equals totc.CatalogId
where
templateCatalog.CreatedBy == 1
orderby templateCatalog.Name
group new { templateCatalog, totc }
by new { templateCatalog.Name, templateCatalog.Id } into result
select new
{
CatalogId = result.Key.Id,
CatalogName = result.Key.Name,
NumberOfTemplates = result.Count()
};
how to assign colour to duplicate values in a list
This my table
| user_id | account_no | zip | date |
| 1 | 123 | 55555 | 12-DEC-09 |
| 1 | 123 | 66666 | 12-DEC-09 |
| 1 | 123 | 55555 | 13-DEC-09 |
| 2 | 456 | 77777 | 14-DEC-09 |
| 2 | 456 | 77777 | 14-DEC-09 |
| 2 | 789 | 77777 | 14-DEC-09 |
| 2 | 789 | 77777 | 14-DEC-09 |
You can assign a color in this way:
var userIdGroups = db.TableName.GroupBy(x => x.user_id).AsEnumerable();
var itemsWithColors = userIdGroups
.SelectMany(g => g.Select((x, index) => index == 0
? new { Item = x, Color = Color.Black }
: new { Item = x, Color = Color.Red }));
Now use a foreach loop to process this query and add these items to your UI control.
I have a collection like this:
Order //Collection
|-OrderId
|-DateOfOrder
|-PartyName
|-OrderDetails //Collection
| |-ItemName
| |-Quantity
| |-Rate
| |-Amount
|-Dispatch //Collection
| |-InvoiceNo
| |-DateOfDispatch
| |-DispatchDetails //Collection
| | |-ItemName
| | |-Quantity
| | |-Rate
| | |-Amount
Now I want to flatten this collection, so that I can show data in below mentioned pattern:
OrderId | DateOfOrder | PartyName | InvoiceNo | DateOfDispatch | Dispatch ItemName | Dispatch Quantity | Dispatch Rate | Dispatch Amount
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
I have tried:
Orders = new ObservableCollection<Order>(orderService.GetAllOrders()
.SelectMany(x => x.Dispatches)
.SelectMany(x => x.DispatchDetails)
.ToList()
);
The relation between OrderDetails and DispatchDetails is not clear to me, and DispatchItemTransactions seems to be missing from your data structure. Anyway, I hope you find this simple approach useful:
foreach(var order in Orders)
foreach(var dispatch in order.Dispatches)
foreach(var dispatchDetail in dispatch.DispatchDetails)
{
// now construct your record object from order.OrderId, order.DateOfOrder, ... , dispatchDetail.Amount
}
For this to work you'll need to construct new Order and Dispatch objects. Also query syntax will make this much easier to read.
Orders = new ObservableCollection<Order>(
from o in orderService.GetAllOrders
from d in o.Dispatches
from dd in d.DispathDetails
select new Order
{
OrderId = o.OrderId,
DateOfOrder = o.DateOfOrder,
PartyName = o.PartyName,
Dispatches = new List<Dispatch>
{
new Dispatch
{
InvoiceNo = d.InvoiceNo
DateOfDispatch = d.DateOfDispatch
DispatchDetails = new List<DispatchDetail> { dd }
}
}
});
Though instead of a collection of Order you might want to just use an anonymous class instead
from o in orderService.GetAllOrders
from d in o.Dispatches
from dd in d.DispathDetails
select new
{
OrderId = o.OrderId,
DateOfOrder = o.DateOfOrder,
PartyName = o.PartyName,
InvoiceNo = d.InvoiceNo
DateOfDispatch = d.DateOfDispatch,
DispatchItemName = dd.ItemName,
DispatchQuantity = dd.Quantity,
DispatchRate = dd.Rate,
DispatchAmount = dd.Amount
}
So I'm attempting to populate a table with seed data in EF5. I have an Enum of all 50 states and DC. I also have a lookup table of RequestTypes with IDs 1-6. It would be something like this:
+----+----------+-------------+------------+
| Id | State | SurveyId | RequestType|
+----+----------+-------------+------------+
| 1 | Alabama | 0 | 1 |
| 2 | Alabama | 0 | 2 |
| 3 | Alabama | 0 | 3 |
| 4 | Alabama | 0 | 4 |
| 5 | Alabama | 0 | 5 |
| 6 | Alabama | 0 | 6 |
+----+----------+-------------+------------+
The model that represents this table:
public class StateSurveyAssignment{
public long Id { get; set; }
public string State { get; set; }
public long RequestTypeId { get; set; }
public long SurveyId { get; set; }
}
And the code to seed the database in the Configuration.cs:
foreach (var state in Enum.GetValues(typeof(State))) {
foreach (var type in context.RequestTypes){
context.StateSurveyAssignments.AddOrUpdate(
ssa => ssa.Id,
new StateSurveyAssignment{
State = state.ToString(),
RequestTypeId = type.Id
}
);
}
}
My problem is that instead of updating/doing nothing to unchanged records, the seed method is duplicating each row. I've attempted to manually set the Id but had no luck.
EDIT:
This is what the database duplication looks like:
+----+----------+-------------+------------+
| Id | State | SurveyId | RequestType|
+----+----------+-------------+------------+
| 1 | Alabama | 0 | 1 |
| 2 | Alabama | 0 | 2 |
| 3 | Alabama | 0 | 3 |
| 4 | Alabama | 0 | 4 |
| 5 | Alabama | 0 | 5 |
| 6 | Alabama | 0 | 6 |
| ...| ... | ... | ... |
|307 | Alabama | 0 | 1 |
|308 | Alabama | 0 | 2 |
|309 | Alabama | 0 | 3 |
|310 | Alabama | 0 | 4 |
|311 | Alabama | 0 | 5 |
|312 | Alabama | 0 | 6 |
+----+----------+-------------+------------+
My Solution
I swear I'd tried setting my own Id at some point but tried it again per the answer and it seems to have worked. My final solution:
int counter = 1;
foreach (var state in Enum.GetValues(typeof(State))) {
foreach (var type in context.RequestTypes){
context.StateSurveyAssignments.AddOrUpdate(
ssa => ssa.Id,
new StateSurveyAssignment{
Id = counter,
State = state.ToString(),
RequestTypeId = type.Id
}
);
counter++;
}
}
The problem could be that the Id property in your StateSurveyAssignment class is an Identity column in the database.
This means that each row is not unique.
For example you try to insert the following several times using AddOrUpdate()
var model = new StateSurveyAssignment
{
State = "Alabama",
RequestTypeId = 1L,
SurveyId = 0L
};
Then each entry would have a different Id and thus you'll have duplicates.
I have DataTable Like this
Thank you Bob Vale for your help
what is (Select(X,i) mean in your linq,
but as i made a mistake in my table
I have this
No | Size | Type | FB | FP
----------------------------------------
100 | 2 | typeA | FB1 | A1
101 | 3 | typeB | FB1 | A1
101 | 4 | typec | FB1 | A1
103 | 4 | typeC | FB2 | A2
103 | 5 | typeD | FB2 | A2
103 | 6 | typeE | FB2 | A2
I want to have some thing like that
No | Size | Type | FB | FP
---------------------------------
100 | 2 | typeA | FB1 | A1
101 | 3 | typeB | FB1 | A1
| 4 | typec | |
103 | 4 | typeC | FB2 | A2
| 5 | typeD | |
| 6 | typeE | |
How can I make it? I can make Group By
var result = from row in cableDataTable.AsEnumerable()
group row by new
{
FB = row.Field<string>("FB"),
FP = row.Field<string>("FP"),
Size = row.Field<int>("Size"),
Type = row.Field<int>("Type"),
no= row.Field<int>("no"),
} into g
select new
{
FB = g.Key.FB,
FP = g.Key.FP,
Size = g.Key.Size,
Type = g.Key.Type
no= g.Key.no
};
but it that could't give the result
thank you for your attention
How about this:
// First declare a conversion from the DataTable to an anon type
var rows = cableDataTable.AsEnumerable()
.Select(x => new {
Size = x.Field<int>("Size"),
Type= x.Field<string>("Type"),
FB = x.Field<string>("FB"),
FP = x.Field<string>("FP")
});
// Now use group by, ordering and select many to select the rows
var result = rows.GroupBy (row => new {row.FB, row.FP} )
.OrderBy (g => g.Key.FB)
.ThenBy(g => g.Key.FP)
.SelectMany(g => g.OrderBy(row => row.Size)
.Select((x,i) =>
new {
Size = x.Size,
Type = x.Type,
FB = (i==0) ? x.FB : null,
FP= (i==0) ? x.FP : null
}));
You can use linq query as
var result = cableDataTable.AsEnumerable().GroupBy(g => new { g.FB, g.FP}).Select(x => x);