How do I match two identical database tables with LINQ? - c#

I want to match 2 identical tables:
sourceProducts (productName, ProductionDate, ManID, shipper, distributer)
CommProducts (productName, ProductionDate, ManID, shipper, distributer)
but the number of rows and the record contents may differ. How do I select a certain record = raw from one table and get its clone record from the other table (e.g., check if the same record exists)? How do I do this using LinQ?
UPDATE: Here's the LINQ code:
protected void checkBtn_Click(object sender, EventArgs e)
{
MyProductsDataContext mySdb = new MyProductsDataContext();
Product mypro = new Product { ManId = int.Parse(TxtManI.Text), ProductName = TxtProN.Text, ProductionDate =DateTime .Parse ( TxtProDat.Text), Shipper = TxtShipI.Text, Distributer = TxtDistI.Text };
var spro = (from p in mySdb.Products
select new { p.ManId, p.ProductName, p.ProductionDate, p.Shipper, p.Distributer }).
Intersect(from s in mySdb.SourceProducts select new { s.ManId, s.ProductName, s.ProductionDate, s.Shipper, s.Distributer });
if (spro != null)
{
LblMessage.Text = "Acceptable product Data Inserted Sucessfully";
InsertData();
}
else
{
LblMessage.Text = "Invalid Product or bad Entry Please retype";
}
}

I would join on ManId and then compare the rest of the values in a where clause:
bool productExists = (
from p in mySdb.Products
join s in mySdb.SourceProducts
on p.ManId equals s.ManId
where p.ProductName == s.ProductName
&& p.ProductionDate == s.ProductionDate
&& p.Shipper == s.Shipper
&& p.Distributer = s.Distributer
select new { p.ManId, p.ProductName, p.ProductionDate, p.Shipper, p.Distributer }
).Any();
if (productExists)
{
LblMessage.Text = "Acceptable product Data Inserted Sucessfully";
InsertData();
}
else
{
LblMessage.Text = "Invalid Product or bad Entry Please retype";
}
I've used Any() to produce an efficient EXISTS SQL query. You could use SingleOrDefault() or FirstOrDefault() instead if you actually need to use the product returned.
I also don't see anywhere that you're using your new Product's ID - you might need to add that filter to the query as well:
Product mypro = new Product { ... };
bool productExists = (
from p in mySdb.Products
where p.ManId equals mypro.ManId
join s in mySdb.SourceProducts
on p.ManId equals s.ManId
...

You can probably do this using a join but I've hobbled together a unit test which shows one way to this
public class TestProduct
{
public int ManId { get; set; }
public string ProductName { get; set; }
public DateTime ProductionDate { get; set; }
public string Shipper { get; set; }
public string Distributor { get; set; }
}
[TestMethod]
public void TestSourceTable()
{
// Set up a test list
var list = new List<TestProduct>();
for (int i=0;i<5;i++)
{
var p = new TestProduct
{
Distributor = "D" + i,
ManId = i,
ProductionDate = DateTime.Now,
ProductName = "P" + i,
Shipper = "S" + i
};
list.Add(p);
}
// Get an existing product
var existingProduct = list[4];
// Get an unknown product
var unknownProduct = new TestProduct()
{
ManId = -1,
Distributor = "",
ProductionDate = DateTime.Now.AddDays(-1),
ProductName = "",
Shipper = ""
};
// product found
Assert.True(list.Any(p => p == existingProduct));
// product not found
Assert.False(list.Any(p => p == unknownProduct));
}

Related

Query SQL Table with Value from MultipleSelectionComboBox

So, I'm using Syncfusion controls and I've a MultipleSelectionCombobox where user can filter multiple arguments.
I have a query which will load a list based on parameters query.
So, first, I have a class to hold my values;
public class Orders
{
public int ID { get; set; }
public string OrderNum { get; set; }
public string Status { get; set; }
public DateTime Date { get; set; }
}
Then, the query:
public IEnumerable<Orders> LoadData()
{
var ctx = new DbContext();
var query = (from o in ctx.tblOrders.AsQueryable()
select new Orders
{
ID = o.OrderID,
OrderNum = o.OrderNum.ToString(),
Status = o.OrderStatus,
Date = o.OrderDate
});
if(CmbOrderStatus.SelectedItems != null)
{
List<string> list = new List<string>();
foreach (SelectedItems obj in CmbOrderStatus.SelectedItems)
{
list.Add(obj.ToString());
}
for(int i = 0; i < list.Count; i++)
{
var value = list[i];
query = query.Where(p => p.Status == value);
}
}
return query.ToList();
}
So, in Database in have many Orders and many OrderStatus, like "Opened", "Delayed", "Closed".
So, if I filter in CmbOrderStatus "Opened" and "Delayed", I get nothing! If only one is selected, I get nothing!
Any help here?
Thanks
The code use only last filter.
Try this:
public IEnumerable<Orders> LoadData()
{
var ctx = new DbContext();
var query = (from o in ctx.tblOrders.AsQueryable()
select new Orders
{
ID = o.OrderID,
OrderNum = o.OrderNum.ToString(),
Status = o.OrderStatus,
Date = o.OrderDate
});
if(CmbOrderStatus.SelectedItems != null)
{
List<string> list = new List<string>();
foreach (SelectedItems obj in CmbOrderStatus.SelectedItems)
{
list.Add(obj.ToString());
}
query = query.Where(p => list.Contains(p.Status));
}
return query.ToList();
}

Conditional Joins With Linq

Is there a way to progressively / conditionally add joins to a query? I am creating a custom reporting tool for a client, and the client is given a list of objects he/she can select to query on. There will always be a base object used in the query ("FWOBid").
So, for example, if the customer selects objects "FWOBid", "FWOItem", and "FWOSellingOption", I'd want to do this:
var query = from fb in fwoBids
// if "FWOSellingOption", add this join
join so in sellingOptions on fb.Id equals so.BidId
// if "FWOItem", add this join
join i in fwoItems on fb.Id equals i.FWOBidSection.BidId
// select "FWOBid", "FWOItem", and "FWOSellingOption" (everything user has selected)
select new { FWOBid = fb, FWOSellingOption = so, FWOItem = i };
The trick is the customer can select about 6 objects that are all related to each other, resulting in many different combinations of joins. I'd like to avoid hard coding those if possible.
One option is to do some custom join combined with left joins.
A decent TSQL backend should not get any drawbacks in terms of performance for always using all the joins, since the optimers would just remove the join if the condition is always false. But this should be checked out.
bool joinA = true;
bool joinB = false;
bool joinC = true;
var query = from fb in fwoBids
join so in sellingOptions on new { fb.Id, Select = true } equals new { Id = so.BidId, Select = joinA } into js
from so in js.DefaultIfEmpty()
join i in fwoItems on new { fb.Id, Select = true } equals new { Id = i.FWOBidSection.BidId, Select = joinB } into ji
from i in ji.DefaultIfEmpty()
join c in itemsC on new { fb.Id, Select = true } equals new { Id = c.BidId, Select = joinC }
select new
{
FWOBid = fb,
FWOSellingOption = so,
FWOItem = i,
ItemC = c
};
In the Linq query syntax this is not possible, or looking at the other answers hardly readable. Not much more readable but another possibility would be to use the extension methods (sort of pseudo code):
bool condition1;
bool condition2;
List<Bid> bids = new List<Bid>();
List<SellingOption> sellingOptions = new List<SellingOption>();
List<Item> items = new List<Item>();
var result = bids.Select(x => new {bid = x, sellingOption = (SellingOption)null, item = (Item)null});
if (condition1)
result = result.Join(
sellingOptions,
x => x.bid.Id,
x => x.BidId,
(x, sellingOption) => new { x.bid, sellingOption, item = (Item)null });
if (condition2)
result = result.Join(
items,
x => x.bid.Id,
x => x.BidId,
(x, item) => new { x.bid, x.sellingOption, item });
Just see this as a sort of a concept. It is essentially the same that Peter Duniho did.
The thing is, if you don't want to immediately join on all options if not necessary, then it won't look that nice. Perhaps you should try to join all now and don't worry about performance. Have you ever measured how slow or fast it might be? Think of it as "I don't need it now!". If performance is indeed a problem, then you can act on it. But if it is not, and you won't know if you never tried, then leave it as the six joins you mentioned.
It's hard to provide a really good example solution without a really good example problem. However, what I mean by "chain the queries" is something like this:
var query = from x in dba select new { A = x, B = (B)null, C = (C)null };
if ((joinType & JoinType.B) != 0)
{
query = from x in query
join y in dbb on x.A.Id equals y.Id
select new { A = x.A, B = y, C = x.C };
}
if ((joinType & JoinType.C) != 0)
{
query = from x in query
join y in dbc on x.A.Id equals y.Id
select new { A = x.A, B = x.B, C = y };
}
That is, based on the appropriate condition, query the previous result with another join. Note that to do this successfully, each query must produce the same type. Otherwise, it's not possible to assign a new query to the previous query result variable.
Note that while in the above, I simply have a separate property for each possible input type, I could have instead had the type simply have properties for the input columns, Id, Name, and then the Text properties from the B and C types (which would have to be named differently in the query result type, e.g. TextB and TextC). That would look like this:
var query = from x in dba select new { Id = x.Id, Name = x.Name,
TextB = (string)null, TextC = (string)null };
if ((joinType & JoinType.B) != 0)
{
query = from x in query
join y in dbb on x.Id equals y.Id
select new { Id = x.Id, Name = x.Name, TextB = y.Text, TextC = x.TextC };
}
if ((joinType & JoinType.C) != 0)
{
query = from x in query
join y in dbc on x.Id equals y.Id
select new { Id = x.Id, Name = x.Name, TextB = x.TextB, TextC = y.Text };
}
Here is a complete code example that includes the above logic in a runnable program:
class A
{
public string Name { get; private set; }
public int Id { get; private set; }
public A(string name, int id)
{
Name = name;
Id = id;
}
public override string ToString()
{
return "{" + Name + ", " + Id + "}";
}
}
class B
{
public int Id { get; private set; }
public string Text { get; private set; }
public B(int id, string text)
{
Id = id;
Text = text;
}
public override string ToString()
{
return "{" + Id + ", " + Text + "}";
}
}
class C
{
public int Id { get; private set; }
public string Text { get; private set; }
public C(int id, string text)
{
Id = id;
Text = text;
}
public override string ToString()
{
return "{" + Id + ", " + Text + "}";
}
}
[Flags]
enum JoinType
{
None = 0,
B = 1,
C = 2,
BC = 3
}
class Program
{
static void Main(string[] args)
{
A[] dba =
{
new A("A1", 1),
new A("A2", 2),
new A("A3", 3)
};
B[] dbb =
{
new B(1, "B1"),
new B(2, "B2"),
new B(3, "B3")
};
C[] dbc =
{
new C(1, "C1"),
new C(2, "C2"),
new C(3, "C3")
};
JoinType joinType;
while ((joinType = _PromptJoinType()) != JoinType.None)
{
var query = from x in dba select new { A = x, B = (B)null, C = (C)null };
if ((joinType & JoinType.B) != 0)
{
query = from x in query
join y in dbb on x.A.Id equals y.Id
select new { A = x.A, B = y, C = x.C };
}
if ((joinType & JoinType.C) != 0)
{
query = from x in query
join y in dbc on x.A.Id equals y.Id
select new { A = x.A, B = x.B, C = y };
}
foreach (var item in query)
{
Console.WriteLine(item);
}
Console.WriteLine();
}
}
private static JoinType _PromptJoinType()
{
JoinType? joinType = null;
do
{
Console.Write("Join type ['A' for all, 'B', 'C', or 'N' for none]");
ConsoleKeyInfo key = Console.ReadKey();
Console.WriteLine();
switch (key.Key)
{
case ConsoleKey.A:
joinType = JoinType.BC;
break;
case ConsoleKey.B:
joinType = JoinType.B;
break;
case ConsoleKey.C:
joinType = JoinType.C;
break;
case ConsoleKey.N:
joinType = JoinType.None;
break;
default:
break;
}
} while (joinType == null);
return joinType.Value;
}
}
I hope this is an improvement over previous answers.
public class Bids
{
public int Id { get; set; }
public double Price { get; set; }
}
public class BidSection
{
public int BidId { get; set; }
}
public class SellingOptions
{
public int BidId { get; set; }
public int Quantity { get; set; }
}
public class Item
{
public int ItemId { get; set; }
public BidSection FWOBidSection { get; set; }
}
public class ConditionalJoin
{
public bool jOpt1 { get; set; }
public bool jOpt2 { get; set; }
public ConditionalJoin(bool _joinOption1, bool _joinOption2)
{
jOpt1 = _joinOption1;
jOpt2 = _joinOption2;
}
public class FBandSo
{
public Bids FWOBids { get; set; }
public SellingOptions FWOSellingOptions { get; set; }
}
public class FBandI
{
public Bids FWOBids { get; set; }
public Item FWOItem { get; set; }
}
public void Run()
{
var fwoBids = new List<Bids>();
var sellingOptions = new List<SellingOptions>();
var fwoItems = new List<Item>();
fwoBids.Add(new Bids() { Id = 1, Price = 1.5 });
sellingOptions.Add(new SellingOptions() { BidId = 1, Quantity = 2 });
fwoItems.Add(new Item() { ItemId = 10, FWOBidSection = new BidSection() { BidId = 1 } });
IQueryable<Bids> fb = fwoBids.AsQueryable();
IQueryable<SellingOptions> so = sellingOptions.AsQueryable();
IQueryable<Item> i = fwoItems.AsQueryable();
IQueryable<FBandSo> FBandSo = null;
IQueryable<FBandI> FBandI = null;
if (jOpt1)
{
FBandSo = from f in fb
join s in so on f.Id equals s.BidId
select new FBandSo()
{
FWOBids = f,
FWOSellingOptions = s
};
}
if (jOpt2)
{
FBandI = from f in fb
join y in i on f.Id equals y.FWOBidSection.BidId
select new FBandI()
{
FWOBids = f,
FWOItem = y
};
}
if (jOpt1 && jOpt2)
{
var query = from j1 in FBandSo
join j2 in FBandI
on j1.FWOBids.Id equals j2.FWOItem.FWOBidSection.BidId
select new
{
FWOBids = j1.FWOBids,
FWOSellingOptions = j1.FWOSellingOptions,
FWOItems = j2.FWOItem
};
}
}
}

How to control quantity and increase

I'm using webservice to add product to basket here the code ;
[WebMethod]
public void calistir(int urunid, string GirenIp)
{
using (Models.DermabonEntities db = new Models.DermabonEntities())
{
var productName = (from i in db.Product
where i.Id == urunid
select i.ProductName).FirstOrDefault();
var productPrice = (from i in db.Product
where i.Id == urunid
select i.ProductPrice).FirstOrDefault();
var productId = (from i in db.Product
where i.Id == urunid
select i.Id).FirstOrDefault();
var productPic = (from i in db.Product
where i.Id == urunid
select i.ProductPicture).FirstOrDefault();
var userIp = GirenIp;
Basket create = new Basket();
create.ProductName = productName;
create.ProductId = productId;
create.ProductPrice = productPrice;
create.ProductPic = productPic;
create.UserId = userIp;
var qua = "2";
create.ProductQuantity = Convert.ToInt32(qua);
db.Basket.Add(create);
db.SaveChanges();
}
}
Here I add quantity of product manually. But I want to control if there is same product increase quantity and if not make quantity 1.
I've tried something like this ;
var CountProduct= db.Basket.FirstOrDefault();
if (CountProduct.ProductId == urunid)
{
CountProduct.ProductQuantity += Convert.ToInt32(adet);
create.ProductQuantity = Convert.ToInt32(adet);
db.SaveChanges();
}
GirenIp = sessionID which comes from ajax , urunId = ProductId which comes from ajax , adet means quantity.
Ajax ;
function sepeteEkle(id) {
var urunid = id;
var GirenIp = $("#userId").val();
$.ajax({
dataType: "json",
type: "POST",
contentType: "application/json",
url: "/Admin/WebService/Control.asmx/calistir",
data: "{'urunid':'" + urunid + "','GirenIp':'" + GirenIp + "' }",
success: function(){
$("#cartContent").load("MiniSepet.aspx #cartContent");
},
error: function () {
$("#cartContent").load("MiniSepet.aspx #cartContent");
}
});
return false;
}
$(document).on('click', '.sepetat', function () {
var nId = $(this).data("id")
sepeteEkle(nId);
});
sepetat= add to basket
basket table ;
public partial class Basket
{
public int Id { get; set; }
public string UserId { get; set; }
public Nullable<int> ProductId { get; set; }
public string ProductName { get; set; }
public Nullable<double> ProductPrice { get; set; }
public Nullable<int> ProductQuantity { get; set; }
public string ProductPic { get; set; }
}
}
You do not want to run multiple LINQ queries on the same object, just to get several properties. That will cause SQL code to be run multiple times (4 times in your example). Just fetch the object once and use its properties.
You also want to clean things up a bit and use a simple pattern like this:
public void calistir(int urunid, string GirenIp)
{
using(Models.DermabonEntities db = new Models.DermabonEntities())
{
// Find the product by primary key
var product = db.Product.Find(urunid);
if (product != null)
{
var productName = product.ProductName;
var productPrice = product.ProductPrice;
var productId = urunid;
var productPic = product.ProductPicture;
var userIp = GirenIp;
// Get existing basket entry if any based on session/user id and product id
Basket basket = dn.basket.FirstOrDefault(x=>x.UserId == userIp && x.ProductId == productId);
if (basket == null)
{
// basket does not already exist, so add new basket
basket = new Basket()
{
// You can use property assignment with constructors
ProductName = productName,
ProductId = productId,
ProductPrice = productPrice,
ProductPic = productPic,
UserId = userIp,
ProductQuantity = 1 // Your initial quantity
}
db.Basket.Add(basket);
}
else
{
// Existing basket, just increase the quantity
basket.ProductQuantity++;
}
db.SaveChanges();
}
}
}
Most of your temporary variables are not actually needed:
public void calistir(int urunid, string GirenIp)
{
using(Models.DermabonEntities db = new Models.DermabonEntities())
{
// Find the product by primary key
var product = db.Product.Find(urunid);
if (product != null)
{
var userIp = GirenIp;
// Get existing basket entry if any based on session/user id and product id
Basket basket = dn.basket.FirstOrDefault(x=>x.UserId == userIp && x.ProductId == urunid);
if (basket == null)
{
// basket does not already exist, so add new basket
basket = new Basket()
{
// You can use property assignment with constructors
ProductName = product.ProductName,
ProductId = product.ProductId,
ProductPrice = product.ProductPrice,
ProductPic = product.ProductPicture,
UserId = userIp,
ProductQuantity = 1 // Your initial quantity
}
db.Basket.Add(basket);
}
else
{
// Existing basket, just increase the quantity
basket.ProductQuantity++;
}
db.SaveChanges();
}
}
}

How to populate `ICollection<T>` property inside a `List<T>` linq

My Class
public partial class CTITLE_CHECKLIST : CError
{
public int Id { get; set; }
[Required(ErrorMessage = "Requerido")]
public int ID_Tipo_Checklist { get; set; }
[Required(ErrorMessage = "Requerido")]
public string Descripcion { get; set; }
public virtual CTipo_CheckList Tipo_CheckList { get; set; }
public ICollection<CSUBTITLE_CHECKLIST> Subtitulos { get; set; }
}
My method :
public List<CTITLE_CHECKLIST> GetCheked(string codigo, int tipoCheckList)
{
try
{
var result = (from a in db.TITLE_CHECKLIST
from t in db.Tipo_CheckList
where a.ID_Tipo_Checklist == t.ID
where a.ID_Tipo_Checklist == tipoCheckList
select new CTITLE_CHECKLIST
{
Descripcion = a.Descripcion,
Id = a.Id,
ID_Tipo_Checklist = a.ID_Tipo_Checklist,
Tipo_CheckList = new CTipo_CheckList
{
Descripcion = t.Descripcion,
ID = t.ID,
ID_Depto = t.ID_Depto
},
Subtitulos = (from s in db.SUBTITLE_CHECKLIST
where s.ID_Title == a.Id
select new CSUBTITLE_CHECKLIST
{
AmountCK = s.AmountCK,
Descripcion = s.Descripcion,
ID = s.ID,
ID_Title = s.ID_Title,
Numeracion = s.Numeracion,
checkList = (from ck in db.CheckList
where ck.ID_Subtitle == s.ID
&& ck.Codigo == codigo
select new CCheckList
{
CK = ck.CK,
Amount = ck.Amount,
Codigo = ck.Codigo,
Codigo_TFile = ck.Codigo_TFile,
Comentario = ck.Comentario,
ID = ck.ID,
ID_Subtitle = ck.ID_Subtitle,
UserCre = ck.UserCre,
UserMod = ck.UserMod
}).FirstOrDefault()
})//here I put ToList
}).ToList();
An my error this :
Error 2 Cannot implicitly convert type 'System.Linq.IQueryable<TROP.Areas.TRAFICO.Controllers.LOGICA.CSUBTITLE_CHECKLIST>' to 'System.Collections.Generic.ICollection<TROP.Areas.TRAFICO.Controllers.LOGICA.CSUBTITLE_CHECKLIST>'. An explicit conversion exists (are you missing a cast?) C:\Users\jmitchell\Documents\Visual Studio 2012\Projects\TROP\TROP\Areas\TRAFICO\Controllers\LOGICA\CTITLE_CHECKLIST.cs 136 49 TROP
And When I put .ToList, where say Here I put ToList it throw an error that say :
LINQ to Entities does not recognize the method 'System.Collections.Generic.List`1[TROP.Areas.TRAFICO.Controllers.LOGICA.CSUBTITLE_CHECKLIST] ToList[CSUBTITLE_CHECKLIST](System.Collections.Generic.IEnumerable`1[TROP.Areas.TRAFICO.Controllers.LOGICA.CSUBTITLE_CHECKLIST])' method, and this method cannot be translated into a store expression.
And I Know that if I change the property subtitles to IEnumerable<T> it will work, but, Im trying to bind this model from MVC4 post, And I doesn't bind with IEnumerable<T>, it bind with a ICollection<T>, List<T> , I am like 1 and a half day trying to figure out this problem.
So the choices are not "do the whole thing in the database" or "do the whole thing in memory". You want to do some of both. Do everything on the DB end that you can, and then when you've done all of that, finish up the remaining operations in memory. This general pattern (mostly leveraging AsEnumerable) will allow you to do this:
(from a in db.TITLE_CHECKLIST
from t in db.Tipo_CheckList
where a.ID_Tipo_Checklist == t.ID
where a.ID_Tipo_Checklist == tipoCheckList
select new //note were using an anonymous type here,
//as the real type can't take a non-list
{
Descripcion = a.Descripcion,
Id = a.Id,
ID_Tipo_Checklist = a.ID_Tipo_Checklist,
Tipo_CheckList = new CTipo_CheckList
{
Descripcion = t.Descripcion,
ID = t.ID,
ID_Depto = t.ID_Depto
},
Subtitulos = from s in db.SUBTITLE_CHECKLIST
where s.ID_Title == a.Id
select new CSUBTITLE_CHECKLIST
{
AmountCK = s.AmountCK,
Descripcion = s.Descripcion,
ID = s.ID,
ID_Title = s.ID_Title,
Numeracion = s.Numeracion,
checkList = (from ck in db.CheckList
where ck.ID_Subtitle == s.ID
&& ck.Codigo == codigo
select new CCheckList
{
CK = ck.CK,
Amount = ck.Amount,
Codigo = ck.Codigo,
Codigo_TFile = ck.Codigo_TFile,
Comentario = ck.Comentario,
ID = ck.ID,
ID_Subtitle = ck.ID_Subtitle,
UserCre = ck.UserCre,
UserMod = ck.UserMod
}).FirstOrDefault()
}//note no ToList
})
//This will ensure that all operators that follow
//are done in memory, not on the DB end
.AsEnumerable()
.Select(checklist => new CTITLE_CHECKLIST
{
Descripcion = checklist.Descripcion,
Id = checklist.Id,
ID_Tipo_Checklist = checklist.ID_Tipo_Checklist,
Subtitulos = Subtitulos.ToList(),
});

Group by with multiple columns using lambda

How can I group by with multiple columns using lambda?
I saw examples of how to do it using linq to entities, but I am looking for lambda form.
var query = source.GroupBy(x => new { x.Column1, x.Column2 });
I came up with a mix of defining a class like David's answer, but not requiring a Where class to go with it. It looks something like:
var resultsGroupings = resultsRecords.GroupBy(r => new { r.IdObj1, r.IdObj2, r.IdObj3})
.Select(r => new ResultGrouping {
IdObj1= r.Key.IdObj1,
IdObj2= r.Key.IdObj2,
IdObj3= r.Key.IdObj3,
Results = r.ToArray(),
Count = r.Count()
});
private class ResultGrouping
{
public short IdObj1{ get; set; }
public short IdObj2{ get; set; }
public int IdObj3{ get; set; }
public ResultCsvImport[] Results { get; set; }
public int Count { get; set; }
}
Where resultRecords is my initial list I'm grouping, and its a List<ResultCsvImport>. Note that the idea here to is that, I'm grouping by 3 columns, IdObj1 and IdObj2 and IdObj3
if your table is like this
rowId col1 col2 col3 col4
1 a e 12 2
2 b f 42 5
3 a e 32 2
4 b f 44 5
var grouped = myTable.AsEnumerable().GroupBy(r=> new {pp1 = r.Field<int>("col1"), pp2 = r.Field<int>("col2")});
Further to aduchis answer above - if you then need to filter based on those group by keys, you can define a class to wrap the many keys.
return customers.GroupBy(a => new CustomerGroupingKey(a.Country, a.Gender))
.Where(a => a.Key.Country == "Ireland" && a.Key.Gender == "M")
.SelectMany(a => a)
.ToList();
Where CustomerGroupingKey takes the group keys:
private class CustomerGroupingKey
{
public CustomerGroupingKey(string country, string gender)
{
Country = country;
Gender = gender;
}
public string Country { get; }
public string Gender { get; }
}
class Element
{
public string Company;
public string TypeOfInvestment;
public decimal Worth;
}
class Program
{
static void Main(string[] args)
{
List<Element> elements = new List<Element>()
{
new Element { Company = "JPMORGAN CHASE",TypeOfInvestment = "Stocks", Worth = 96983 },
new Element { Company = "AMER TOWER CORP",TypeOfInvestment = "Securities", Worth = 17141 },
new Element { Company = "ORACLE CORP",TypeOfInvestment = "Assets", Worth = 59372 },
new Element { Company = "PEPSICO INC",TypeOfInvestment = "Assets", Worth = 26516 },
new Element { Company = "PROCTER & GAMBL",TypeOfInvestment = "Stocks", Worth = 387050 },
new Element { Company = "QUASLCOMM INC",TypeOfInvestment = "Bonds", Worth = 196811 },
new Element { Company = "UTD TECHS CORP",TypeOfInvestment = "Bonds", Worth = 257429 },
new Element { Company = "WELLS FARGO-NEW",TypeOfInvestment = "Bank Account", Worth = 106600 },
new Element { Company = "FEDEX CORP",TypeOfInvestment = "Stocks", Worth = 103955 },
new Element { Company = "CVS CAREMARK CP",TypeOfInvestment = "Securities", Worth = 171048 },
};
//Group by on multiple column in LINQ (Query Method)
var query = from e in elements
group e by new{e.TypeOfInvestment,e.Company} into eg
select new {eg.Key.TypeOfInvestment, eg.Key.Company, Points = eg.Sum(rl => rl.Worth)};
foreach (var item in query)
{
Console.WriteLine(item.TypeOfInvestment.PadRight(20) + " " + item.Points.ToString());
}
//Group by on multiple column in LINQ (Lambda Method)
var CompanyDetails =elements.GroupBy(s => new { s.Company, s.TypeOfInvestment})
.Select(g =>
new
{
company = g.Key.Company,
TypeOfInvestment = g.Key.TypeOfInvestment,
Balance = g.Sum(x => Math.Round(Convert.ToDecimal(x.Worth), 2)),
}
);
foreach (var item in CompanyDetails)
{
Console.WriteLine(item.TypeOfInvestment.PadRight(20) + " " + item.Balance.ToString());
}
Console.ReadLine();
}
}

Categories

Resources