Anyone can help to convert below SQL query to c# LinQ Lambda Expression? Thanks
tbl_CLASS
ClassID Student
Class1 A
Class1 B
Class1 C
Class2 B
Class2 C
Class3 C
Result
Class A B C
Class1 Y Y Y
Class2 N Y Y
Class3 N N Y
SELECT a.ClassID,
A=case when c.ClassID is null then 'N' else 'Y' end,
B=case when B.ClassID is null then'N' else 'Y' end,
C='Y'
FROM tbl_CLASS a
Left join tbl_CLASS b on a.ClassID=b.ClassID AND b.Student='B'
Left join tbl_CLASS c on a.ClassID=c.ClassID AND c.Student='A'
WHERE a.Student='C'
GROUP by a.ClassID,case when c.ClassID is null then 'N' else 'Y' end,case when B.ClassID is null then'N' else 'Y' end
List<Class1> myList = GetClass();
var query = myList
.GroupBy(c => c.ClassID)
.Select(g => new {
ClassID = g.Key,
A = g.Count(c => c.Student=="A")>0?"Y":"N",
B = g.Count(c => c.Student=="B")>0?"Y":"N",
C = g.Count(c => c.Student=="C")>0?"Y":"N"
});
GetClass is get your data
public class Class1
{
public Int32 ClassID {get;set;}
public String A{get;set;}
public String B{get;set;}
public String C{get;set;}
}
When students are dynamic it means you need a result class for result rows like this:
class ResultRow
{
public ResultRow()
{
Students = new Dictionary<string, string>();
}
public string Class { get; set; }
public IDictionary<string, string> Students { get; set; }
}
Because you need dynamic columns for students.
Now I can generate a result similar to your expected result with this code:
var res = tblClass
.GroupBy(g=> g.ClassId)
.Select(c =>
{
var rr = new ResultRow {Class = c.Key};
foreach (var r in tblClass.GroupBy(gg=> gg.Student))
{
rr.Students[r.Key] = "N";
}
foreach (var r in c.Where(w=> w.ClassId == c.Key))
{
rr.Students[r.Student] = "Y";
}
return rr;
})
.toList(); //optional
You can also add these two method to ResultRow class:
public string GetHeader()
{
return Students.Aggregate("Class", (current, s) => current + "|" + s.Key);
}
public string GetSolidRow()
{
return Students.Aggregate(Class, (current, s) => current + "|" + s.Value);
}
[ Demo Here ]
HTH
cannot convert from System.Collections.Generic.List<> to System.Collections.Generic.IEnumerable<>
public SystemAccessList GetAccessList(SystemAccessList systemAccessList)
{
var qresult = db.tbl_SystemAccessList
.GroupBy(g => g.ClassID)
.AsEnumerable().Select(c =>
{
var rr = new ResultRow { Class = c.Key };
foreach (var r in db.tbl_SystemAccessList.GroupBy(gg => gg.StudentID))
{
rr.Student[r.Key] = "N";
}
foreach (var r in c.Where(w => w.ClassID == c.Key))
{
rr.Student[r.StudentID] = "Y";
}
return rr;
}).ToList();
systemAccessList.SystemAccessList.AddRange(qresult);
return systemAccessList;
}
Related
I have two lists of data (they are using the same class "SaleNumber").
Each list contains a list of sale numbers. The first list is taken from the danish "DK" database and the other from the swedish database.
Right now I am looping through the danish list For each item I loop through I find the item with the same variant id in the swedish list and then I join the data into a new list called saleNumbers.
The problem with this is that because I loop through the danish list then if the danish list doesn't have salenumbers for that variant id then it won't loop through this variant. If this happens then the swedish list item won't be added either - and therefore the salenumbers item won't be created - even though it should - it should have a 0 in salenumbers.totalsalesDK and the actual salenumber for the salenumbers.totalsalesSE.
How do I merge the two together into salenumbers without missing any variants?
I still want the structure retained - so that for instance I have the SaleNumbers.TotalSales showing sum of totalsales for both dk and se together. And the SaleNumbers.TotalSalesDK showing DK sales and SaleNumbers.TotalSalesSE showing SE sales for that item. The primary unique key is always the variantId. Here is my current code:
private List<SaleNumber> ConvertDataTableToSaleNumbers(DataTable dt)
{
List<SaleNumber> saleNumbers = new List<SaleNumber>();
foreach (DataRow dr in dt.Rows)
{
saleNumbers.Add(new SaleNumber() { ProductId = int.Parse(dr["productid"].ToString()), TotalSales = int.Parse(dr["totalsales"].ToString()), VariantId = int.Parse(dr["variantid"].ToString()) });
}
return saleNumbers;
}
DataTable dtDK = new Shoply.Data.DLOrderDetail().GetNumberOfSalesSinceOrderId(constDaysAgo,
Shoply.Data.DLBasis.GetTheConnectionToTheLanguage("dk"));
DataTable dtSE = new Shoply.Data.DLOrderDetail().GetNumberOfSalesSinceOrderId(constDaysAgo,
Shoply.Data.DLBasis.GetTheConnectionToTheLanguage("se"));
List<SaleNumber> saleNumbersDK = ConvertDataTableToSaleNumbers(dtDK);
List<SaleNumber> saleNumbersSE = ConvertDataTableToSaleNumbers(dtSE);
var saleNumbers = saleNumbersDK.SelectMany
(
foo => saleNumbersSE.Where(bar => foo.VariantId == bar.VariantId).DefaultIfEmpty(),
(foo, bar) => new SaleNumber
{
VariantId = foo.VariantId,
ProductId = foo.ProductId,
TotalSales = foo.TotalSales + (bar == null ? 0 : bar.TotalSales),
TotalSalesDK = foo.TotalSales,
TotalSalesSE = (bar == null ? 0 : bar.TotalSales)
}
);
EDIT:
Code updated to perform outerjoin
How about using Join in Linq.
Simple dotnetfiddle can be seen here : Dotnetfiddle link
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main(string[] args)
{
List<SaleNumber> saleNumbersDK = new List<SaleNumber> {
new SaleNumber() { VariantId="a",ProductId="A",TotalSales=10 },
new SaleNumber() { VariantId="b",ProductId="B",TotalSales=20 }
};
List<SaleNumber> saleNumbersSE = new List<SaleNumber> {
new SaleNumber() { VariantId="a",ProductId="A",TotalSales=10 },
new SaleNumber() { VariantId="c",ProductId="c",TotalSales=30 }
};
var innerjoin = saleNumbersDK.Join(saleNumbersSE, d => d.VariantId, s => s.VariantId, (d, s) =>
{
return new SaleNumber()
{
VariantId = d.VariantId,
ProductId = d.ProductId,
TotalSales = d.TotalSales+ (s == null ? 0 : s.TotalSales),
TotalSalesDK = d.TotalSales,
TotalSalesSE = (d == null ? 0 : d.TotalSales)
};
});
var pendingright= saleNumbersSE.Except(innerjoin, new CustomComparer());
var pendingleft = saleNumbersDK.Except(innerjoin, new CustomComparer());
var salesNumber= innerjoin.Concat(pendingright).Concat(pendingleft);
foreach (var sale in salesNumber)
{
Console.WriteLine(sale);
}
//Console.ReadLine();
}
}
public class SaleNumber
{
public string VariantId { get; set; }
public string ProductId { get; set; }
public int TotalSales { get; set; }
public int TotalSalesDK { get; set; }
public int TotalSalesSE { get; set; }
public override string ToString()
{
return VariantId+"-"+ProductId+"-"+TotalSales+"-"+TotalSalesDK+"-"+TotalSalesSE;
}
}
public class CustomComparer : IEqualityComparer<SaleNumber>
{
public bool Equals(SaleNumber x, SaleNumber y)
{
return x.VariantId == y.VariantId;
}
public int GetHashCode(SaleNumber obj)
{
return obj.VariantId.GetHashCode();
}
}
Assuming ProductId is the same for DK and SE you can use a group by function like this to get the result you want.
testDK.ForEach(s => s.TotalSalesDK = s.TotalSales);
testSE.ForEach(s => s.TotalSalesSE = s.TotalSales);
testDK.Concat(testSE)
.GroupBy(s => s.VariantId)
.Select(g => new SaleNumber() {
VariantId = g.First().VariantId,
ProductId=g.First().ProductId,
TotalSales = g.Sum(s=>s.TotalSalesDK) + g.Sum(s=>s.TotalSalesSE),
TotalSalesDK=g.Sum(s=>s.TotalSalesDK),
TotalSalesSE=g.Sum(s=>s.TotalSalesSE)
}).ToList()
You can use Concat and ToList methods:
var allProducts = productCollection1.Concat(productCollection2)
.Concat(productCollection3)
.ToList();
I have a scenario in following nested
--Orders (List)
----Products (List)
------Manufacturers (List)
FIELDS
-Name
-Address
-City
In this scenario, I would need to execute query which will filter on City of Manufacturers and returns Orders, Products & only matching city manufacturers
I tried to put following query, however I am getting all list of Products even though city doesn't match to Manufacturers.
var filteredOrders = from o in Orders
from t in o.Products
where t.Manufacturers.Any(v => v.City == "Hartford")
select o;
Or even if I change from select o to 'select t.Manufacturers' I am getting all list of Manufacturers irrespective of city filter.
Luckily I got W3school SQL sample which matches to my scenario.
https://www.w3schools.com/sql/trysql.asp?filename=trysql_op_or
SQL Query:
SELECT o.OrderId, p.ProductName, s.*
FROM [Orders] o
JOIN OrderDetails od ON o.OrderId = od.OrderId AND o.orderId = 10248
JOIN Products p ON od.ProductId = p.ProductId
JOIN Suppliers s ON p.SupplierId = s.SupplierId and s.City ='Singapore'
I would flatten everything and then only filter on cities you want:
class Manufacturer
{
public string Name;
public string Address;
public string City;
}
class Product
{
public Manufacturer[] Manufacturers;
}
class Order
{
public Product[] Products;
}
static void Main(string[] args)
{
var cities = new string[] { "a", "b" };
Order[] orders = null;
orders.SelectMany(o => o.Products.SelectMany(p => p.Manufacturers.Select(m => new { o, p, m })))
.Where(g => cities.Contains(g.m.City))
.ToList();
}
Alternatively, if you want to return new Orders (because they have a different Products, it MUST point to a newly allocated Object) you could have this instead:
var newOrders = orders.Select(o => new Order()
{
Products = o.Products
.Select(p => new Product()
{
Manufacturers = p.Manufacturers.Where(m => cities.Contains(m.City)).ToArray()
})
.Where(m => m.Manufacturers.Length > 0).ToArray()
}).Where(p => p.Products.Length > 0).ToArray();
I finally tried to put everything together and got the expected output.
var fp = orders.Select(o =>
{
o.products = o.products.Select(p =>
{
p.manufacturers.RemoveAll(m => m.City != "Hartford");
return p;
}).ToList();
return o;
});
Please suggest if anyone has better solution
You are applying your City filter wrong. It is this line.
where t.Manufacturers.Any(v => v.City == "Hartford")
Any return true, at least one of the manufacturers has City property as "Hartford" so basically your query is something like this
var filteredOrders = from o in Orders
from t in o.Products
where true//←This is the problem
select o;
What you need to do is in fact
where t.Manufacturers.City == "Hartford"
I hope this helps
Example:
var cityNames = new List<string> {"New York",
"Atlanta",
"Hartford",
"Chicago"
};
var anyResult = cityNames.Any(x=>x== "Hartford"); //TRUE
var whereResult = cityNames.Where(x => x == "Hartford"); //IEnumerable<string>, in this case only one element
I cannot think of a way which can completely avoid creating new objects, as the parent object's list property cannot be filtered directly. You can make use of the same class though.
Also I use two separate queries in order to create a new list in parent / grandparent object.
I have made a small demo to demonstrate the idea (below has equivalent code):
http://ideone.com/MO6M6t
The city I try to select is "tmp" which only under parent p3, which only belongs to grand parent g1, g3
The expected output is:
g1
p3
tmp
g3
p3
tmp
using System;
using System.Collections.Generic;
using System.Linq;
public class Test
{
public class GrandParent{
public List<Parent> parentList{ get; set; }
public string name{ get; set; }
public GrandParent(string name){
this.name = name;
this.parentList = new List<Parent>();
}
}
public class Parent{
public List<Child> childList{ get; set;}
public string name{ get; set; }
public Parent(string name){
this.name = name;
this.childList = new List<Child>();
}
}
public class Child{
public string city{ get; set;}
public Child(string city){
this.city = city;
}
}
public static void Main()
{
Child c1 = new Child("ABC"), c2 = new Child("123"), c3 = new Child("tmp");
Parent p1 = new Parent("p1"), p2 = new Parent("p2"), p3 = new Parent("p3");
GrandParent g1 = new GrandParent("g1"), g2 = new GrandParent("g2"), g3 = new GrandParent("g3");
p1.childList.Add(c1); p1.childList.Add(c2);
p2.childList.Add(c2);
p3.childList.Add(c3);
g1.parentList.Add(p1); g1.parentList.Add(p2); g1.parentList.Add(p3);
g2.parentList.Add(p2);
g3.parentList.Add(p3);
List<GrandParent> repo = new List<GrandParent>{g1, g2, g3};
var filteredParents = from g in repo
from p in g.parentList
where p.childList.Any(c => c.city == "tmp")
select new Parent(p.name){
childList = p.childList.Where(c => c.city == "tmp").ToList()
};
var filteredGrandParents = from g in repo
from p in g.parentList
where filteredParents.Any(fp => fp.name == p.name)
select new GrandParent(g.name){
parentList = g.parentList.Where(pp => filteredParents.Any(fp => fp.name == pp.name)).ToList()
};
foreach(var g in filteredGrandParents){
Console.WriteLine(g.name);
foreach(var p in g.parentList){
Console.WriteLine("\t" + p.name);
foreach(var c in p.childList){
Console.WriteLine("\t\t" + c.city);
}
}
Console.WriteLine();
}
}
}
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
};
}
}
}
Is it possible to search in an IQueryable
public static IQueryable<object> SearchAllFields(IQueryable<object> query, string term)
{
query = query.Where(q => q.Property1 == term);
query = query.Where(q => q.Property2 == term);
query = query.Where(q => q.Property3 == term);
return query;
}
Lets say I want to compare the search term to each of the properties that the object might have, without knowing before what properties the object might have.
Edit:
I am attempting to create a generic DataTable solution to display any tabular information that might be necessary (orders, books, customers, etc.)
To test the concept I'm using the ApplicationLogs table in my database. The DataTable looks as follows:
Lets say when typing in that search box I want to search for that value in all the columns that might be displayed. The query that populates the table:
IQueryable<object> query = (from log in db.ApplicationLog
orderby log.LogId descending
select new
{
LogId = log.LogId,
LogDate = log.LogDate.Value,
LogLevel = log.LogLevelId == 1 ? "Information" : log.LogLevelId == 2 ? "Warning" : "Error",
LogSource = log.LogSourceId == 1 ? "Www" : log.LogSourceId == 2 ? "Intranet" : "EmailNotification",
LogText = log.LogText
});
As you can see, this query will determine what the properties of the object will be. The example is taken from the logs table, but it can come from any number of tables. Then, if I want to call the generic search method from the original post:
query = DataTableHelper.SearchAllFields(query, pageRequest.Search);
You can use reflection to search through all the properties of the element, but if you want to return all rows where any property matches then you need to use predicatebuilder to build the applied query instead Where().
This example code will return both instances of Foo where A,B and C are "a". And the instances of Bar where E, F and G are "a". Also added example of anonymous type.
class Program
{
private class Foo
{
public string A { get; set; }
public string B { get; set; }
public string C { get; set; }
}
private class Bar
{
public string E { get; set; }
public string F { get; set; }
public string G { get; set; }
}
static void Main(string[] args)
{
var list = new List<Foo>
{
new Foo { A = "a", B = "a", C = "a" },
new Foo { A = "a2", B = "b2", C = "c2" },
new Foo { A = "a3", B = "b3", C = "c3" },
};
var list2 = new List<Bar>
{
new Bar { E = "a", F = "a", G = "a" },
new Bar { E = "a2", F = "b2", G = "c2" },
new Bar { E = "a3", F = "b3", G = "c3" },
};
var q1 = Filter(list.AsQueryable(), "a");
var q2 = Filter(list2.AsQueryable(), "a");
foreach (var x in q1)
{
Console.WriteLine(x);
}
foreach (var x in q2)
{
Console.WriteLine(x);
}
var queryable = list.Select(p => new
{
X = p.A,
Y = p.B,
Z = p.C
}).AsQueryable();
var q3 = Filter(queryable, "a");
foreach (var x in q3)
{
Console.WriteLine(x);
}
Console.ReadKey();
}
private static IQueryable<object> Filter(IQueryable<object> list, string value)
{
foreach (var prop in list.ElementType.GetProperties())
{
var prop1 = prop;
list = list.Where(l => Equals(prop1.GetValue(l, null), value));
}
return list;
}
}
class Program
{
static void Main(string[] args)
{
MyDatabaseEntities entities = new MyDatabaseEntities();
var result = from c in entities.Categories
join p in entities.Products on c.ID equals p.IDCategory
group p by c.Name into g
select new
{
Name = g.Key,
Count = g.Count()
};
Console.WriteLine(result.ToString());
Console.ReadLine();
}
}
How can I extract the values from ths result set so I can work with them?
foreach (var item in result)
{
var name = item.Name;
var count = item.Count;
...
}
This will only work inside the same method where the LINQ query is located, since the compiler will only then know which properties are available in the anonymous object type (new { }) used in your LINQ select.
If you return a LINQ query to a calling method, and you want to access it in the way shown above, you'd have to define an explicit type and use it in your LINQ query:
class NameCountType
{
public string Name { get; set; }
public int Count { get; set; }
}
...
return from ... in ...
...
select new NameCountType
{
Name = ...,
Count = ...,
};
For example:
foreach (var x in result)
{
Console.WriteLine(x.c.Name);
}
var results = (from myRow in ds.Tables[0].AsEnumerable()
where myRow.Field<String>("UserName") == "XXX"
select myRow).Distinct();
foreach (DataRow dr in results)
UserList += " , "+dr[0].ToString();