LINQ query not showing in DGV - c#

I have been researching this for some time, so if I missed a topic somewhere please point me in the right direction and accept my apologies.
I am performing a LINQ query on an incoming DataTable and setting up new columns based on the filtering done. The information being passed in is a single row containing the columns: CompanyName, CustomerID, LastName, FirstName, ContactTitle.
My question is, am I over-filtering the information to the point where it will return nothing to the DGV, or have I done something else wrong?
What I am trying to do is query another table based on the information passed in from the DataTable. Here is my query:
var query = (from id in IncomingOrderDetails.AsEnumerable()
from o in db.Orders
from c in db.Customers
from r in db.Regions
where (id.Field<int>("OrderID") == o.OrderID)
where (o.CustomerID == c.CustomerID)
where (c.Region == r.RegionDescription)
select new
{
CustomerID = c.CustomerID,
CompanyName = c.CompanyName,
ContactName = c.ContactName,
RegionDescription = r.RegionDescription,
Country = c.Country,
Phone = c.Phone
}).ToList();
custInfoDGV.DataSource = query;

This line:
where (c.Region == r.RegionDescription)
...looks dubious. If c.Region = r.RegionDescription, why do you need to bring in r at all? All you use it for is retrieving the RegionDescription.
I don't know your tables, but joining two fields that don't match would certainly produce 0 records returned. :)

Related

How to apply Not In Linq?

I have tow tables - OrderRequisition and Order. I can show all the records from OrderRequisition table using linq query:
var list = (from r in db.OrderRequisition
select new SalesOrderViewModel
{
OrderId = r.OrderId ,
OrderNo = r.OrderNo
}).ToList();
I want to show only those records from OrderRequisition table which are not included in Order table. Any clue
Thanks
Partha
A simple approach that might be efficient enough because your database is able to optimize it:
var list = db.OrderRequisition
.Where(or => !db.Order.Any(o => o.OrderId == or.OrderId))
.ToList();
(skipped the SalesOrderViewModel initialization because not relevant for the question)

how to get the max value of id from second table using join in entity framework in asp.net c#

I have two tables, from 1st table i want to get all records and from 2nd table i want the max id value of that record. I am using entity framework in asp.net c#.
i tried the below code but it takes only single record from first table i.e tblblogs. and leave all the records, how to get all those records by using this query? plz help me out I'll be very grateful to you. Thanks !
var query= (from c in db.tblBlogs join a in db.tblBlogMedias on c.id
equals a.BlogId where c.id==db.tblBlogMedias.Max(p=>p.id)
select new
{}
If I understood, you want to get an object with specific fields of Blogs and a list of tblBlogMedias.
You could try this code:
var query2 = (from c in db.tblBlogs
orderby c.Id descending
group c.tblBlogMedias by new { c.Id, c.Name } into gb //It will show Id and name of tblBlogs, you can use more fields if you want
select new {
Id = gb.Key.Id,
Name = gb.Key.Name, //I don't know if you have this field, but you should change it
SecondTable = gb.ToList()
})
.OrderByDescending(o => o.Id) //this orderby with FirstOrDefault() replace where c.id==db.tblBlogMedias.Max(p=>p.id)
.FirstOrDefault();

How get a specific value from a query in Linq

I am just starting learning about Linq. I wrote some examples but there is a doubt that I haven't been able to solve.
I am working with the Northwind database, I just used the tool called SqlMetal in order to make all the modeling.
Right now I just wrote the following query:
var q = from c in db.Customers
from o in c.Orders
where c.City == "London"
select new { c, o };
I know that this query brings to me a resulting set of data that contains all the columns of the Customers and Orders tables for the given condition (c.City == "London"). But my question is:
After executing that query, How can I get the value of the column Customers.CustomerID and Orders.OrderID FROM THE VARIABLE q?
Maybe this is a silly question but I have been struggling with this for a couple hours, thanks in advance.
var theSoleItem = q.First();
theSoleItem.CustomerID
theSoleItem.OrderID
Also, if that was the only columns you cared about, your initial query would be faster with:
select new {c.CustomerID, o.OrderID}
You could also change the names as you go:
select new {CustID = c.CustomerID, OrdID = o.OrderID}
The latter being the only option if rather than directly referencing a property, you reference a method call.
The variable q is now a sequence of anonymous objects that have two objects in it: Customer and Order. You can easy iterate over it:
foreach(var item in q)
{
Console.WriteLine("CustomerID = " + item.CustomerID + " order ID = " + item.OrderID);
}

linq-to-sql conditional read

I'm writing a query that looks like this:
var TheOutput = (from x in MyDC.MyTable
where.....
select new MyModel()
{
MyPropID = (from a in MyDC.MyOtherTable
where....
select a.ElementID).SingleOrDefault(),
MyPropData = (from a in MyDC.MyOtherTable
where a.ElementID == MyPropID
select a.ElementData).SingleOrDefault(),
}
I'm filling up MyModel with several properties from the database. Two of these properties are filled by reading another table. At the moment, I first read MyPropID to see if there's an element in the other table and then I read the other table again to get the data, regardless of whether or not an ID was retrieved.
How can I eliminate this second read if I know, from reading MyPropID and returning a null, that there's no data that matches the where a.ElementID == MyPropID clause.
Thanks.
var TheOutput = (from x in MyDC.MyTable
where.....
let id = (from a in MyDC.MyOtherTable
where....
select a.ElementID).SingleOrDefault()
select new MyModel()
{
MyPropID = id,
MyPropData = (from a in MyDC.MyOtherTable
where id != null && a.ElementID == id
select a.ElementData).SingleOrDefault()
}
If your code would create a single SQL statement from this query I do not think checking for null would matter. If this query would result in multiple SQL statements it might.

How to get data from two SQL tables into .net

Previously, I asked a question about getting data from two tables where I take one row in a table and join it with several rows in another table. Here's the link to that discussion: SQL Select data from two tables (one row -> multiple rows)
Here is my SQL code:
SELECT
customer.fName, customer.lName, phone.phoneNumber
FROM
Customers customer
INNER JOIN phoneNumbers phone ON
customer.customerId = phone.customerId
What I would like to know now is: what is the best way to get this data organized in .net?
Let's suppose I have a C# class as following:
public class CustomerDetails
{
int customerId;
string fname;
string lName;
List<string> phoneNumbers;
}
For the sake of discussion, let's suppose that the above SQL query returns the following result:
fname, lname, phoneNumber
"John", "Smith", "111-111"
"Jane", "Doe", "222-1111"
"Jane", "Doe", "222-2222"
At a glance, I see that I have two customers; one has one phone number and the other has two phone numbers. How can I write code to efficiently parse this in C#?
One option is to use LINQ to create a instance of the CustomerDetails class.
Let me know if you would like an example.
Example 1:
List<CustomerDetails> customers = db.Customers.Select(c => new CustomerDetails(){
customerId = c.customerID,
fname = c.fName,
lName = c.lName,
phoneNumbers = (from p in db.PhoneNumbers where p.customerID == c.customerID select p.phoneNumber1).ToList<String>()});
Example 2:
List<CustomerDetails> custs = (from c in db.Customers
select new CustomerDetails()
{
customerId = c.customerID,
fname = c.fName,
lName = c.lName,
phoneNumbers = (from p in db.PhoneNumbers where p.customerID == c.customerID select p.phoneNumber1).ToList<String>()
}).ToList<CustomerDetails>();
I understand that you are looking for ORM object-relational mapping. In .NET I can recommend IBatis.net or LINQ.
Solution 1:
I assume that the records are sorted by name in the SQL query's results and that you also select the customerID. Appending "ORDER BY customer.fName, customer.lName" to your original query will do the trick.
I'll assume that you get your result in a DataReader, so you can do the following:
// Lets start by declaring a collection for our records
List<CustomerDetails> myRecords = new List<CustomerDetails>();
// Iterate all records from the results and fill our collection
while (yourReader.Read())
{
int customerID = int.Parse(yourReader["customerID"]);
int nrRecords = myRecords.Count;
if (nrRecords > 0 && myRecords[nrRecords - 1].customerId == customerID)
{
myRecords[nrRecords - 1].phoneNumbers.Add(yourReader["phoneNumber"]);
}
else
{
CustomerDetails newCustomerDetails = new CustomerDetails();
newCustomerDetails.customerId = customerID;
newCustomerDetails.fName = yourReader["fName"];
newCustomerDetails.lName = yourReader["lName"];
List<string> phoneNumberList = new List<string>();
phoneNumberList.Add(yourReader["phoneNumber"]);
newCustomerDetails.phoneNumbers = phoneNumberList;
myRecords.Add(newCustomerDetails);
}
}
P.S. If ordering the list is not an option, then you can't just check the latest added records customerid - instead you'll need to iterate through the myRecords list and search for the existance of it. This can be done in many ways including with myRecords.Contains() or with a foreach.
Solution 2:
Do the telephone number grouping directly from SQL. Create a function for selecting a comma separated string with all the telephone numbers of a particular customer:
CREATE FUNCTION [dbo].[GetCommaSeparatedPhoneNumbers]
(
#customerID int
)
RETURNS varchar(max)
AS
BEGIN
declare #output varchar(max)
select #output = COALESCE(#output + ', ', '') + phoneNumbers
from phoneNumbers
where customerId = #customerID
return #output
END
GO
Then you can nicely select the list of all customer you want:
SELECT customerId, dbo.GetCommaSeparatedPhoneNumbers(customerId)
FROM Customers
GROUP BY customerId
This will return:
"John", "Smith", "111-111"
"Jane", "Doe", "222-1111,222-2222"
Now it's all a question of parsing the results with a foreach or while loop, but no checking for existance is needed. Just split the string at ',' and insert the values into the List. If there is a chance, that there will be no phone numbers for some customers, then you can filter that field for null.
PS. Will not work if there is a comma as pointed out by BQ in his comment.
Iterate over the result, for each row check if it is in your list of costumers, if not, add a new one, if yes, add the phone number to the existing one.
Of course, you shouldn't parse the string use appropiate classes to access the database, like ado.net.

Categories