linq query displaying result twice - c#

pd is my page ;
ProductDetail pd = new ProductDetail();
fetching data and strong it in data
var data =
from product in db.Products
from orders in db.Orders
from od in db.OrderDetails
from dpt in db.Dpts
where orders.CId.Equals(
(from name in db.Companies
where name.Cname.Equals(selectedcomp)
select name.CId).FirstOrDefault())
&& od.OrdId.Equals(orders.OrdId)
&& product.PId.Equals(od.PId)
select new
{
orders.Billno ,
orders.Date,
orders.pharm ,
product.Pname,
product.Purchasedate,
product.Purchaserate,
product.Salesrate,
product.Supplier,
od.Quantity,
od.Amount
};
it displays the value of data twice in listbox.
pd.ProductDescription.ItemsSource =
(from dat in data
select dat).ToList();

I think your problem is the cross join to the Dpts table. You don't use the results from that table in the where or select, so I don't think you need it. Try removing from dpt in db.Dpts and see if that fixes your problem. My guess is that you are getting n duplicates where n is the total number of rows in db.Dpts.

#juharr is right. You don't use db.Dbts in where clause, so you cross join duplicates results. Probably in db.Dbts table you have 2 records.
I think that you should work on your query.
Few tips:
We don't use cross joins, rather we use join statement
You should get CId before executing your main query
Probably You don't have foreign keys in your database, you should consider that

When getting duplicate items from a query in LINQ or SQL, first check for bad data, then investigate it as a bad join. Your best bet is to strip it down to one table, then add the joins in one-by-one until you get your duplication. Then make that join specific enough that it stops duplicating.

Related

MSSQL Query Not Returning Null Columns/Results

I'm kind of new to SQL queries so this is probably something easily fixed, but I can't seem to find any answers.
I've got a bunch of related tables. E.g.
SPClients contains iClientID and sName, SPDocTypes contains iDocTypeID and sName, SPCreditor contains iCreditorID and sName
and then
SPDocIndex contains iIndexID, and then foreign keys to iClientID, iDocTypeID and iCreditorID listed above.
If I do a simple SELECT * FROM SPDocIndex I get all results, with just the IDs being displayed, which isn't much use when bound to a datagrid. So I use an inner join so the actual names appear rather than just their IDs, like so:
SELECT * FROM SPDocIndex
INNER JOIN SPClients ON SPDocIndex.iClientID=SPClients.iClientID
INNER JOIN SPDocType ON SPDocIndex.iDocTypeID=SPDocType.iDocTypeID
INNER JOIN SPCreditor ON SPDocIndex.iCreditorID=SPCreditor.iCreditorID
And the query "works" but it only returns rows that have data in all three columns. If the iCreditorID column of SPDocIndex is null, then that row is NOT returned...but I would like all rows to be returned irrespective of whether the columns are null or not.
Benny - some of the others responded in the comments, that you'll need to adjust your join to a left join instead of an inner join; indeed, that is the case here. Please check out this link for a quick tutorial on the differences between SQL joins.
https://www.w3schools.com/sql/sql_join.asp
Inner Join will always return the return the matching records within two table. In order to get the all the records from first table and matching record of second table you must use left join as shown below. Please try below and let me know if you have any further issues.
SELECT * FROM SPDocIndex
LEFT JOIN SPClients ON SPDocIndex.iClientID=SPClients.iClientID
LEFT JOIN SPDocType ON SPDocIndex.iDocTypeID=SPDocType.iDocTypeID
LEFT JOIN SPCreditor ON SPDocIndex.iCreditorID=SPCreditor.iCreditorID

EF query using exists throws outofmemory exception

Im trying to get a list of Shop_Orders where their order_num value does not exist in a table called WarhouseOrder. This table contains 500K records and there is an index on OrderNo. List<Shop_Order> contains approx 150 items, each of which has an order_num. When this code is executed, it seems very inefficient, slow and results in an outofmemory exception. Is there a better way to do this?
List<Shop_Order> new_orders = (from a in osource.order
where !ctx.WarehouseOrders.ToList()
.Exists(o => o.OrderNo == a.order_num) select a).ToList();
WarehouseOrders.ToList() downloads all warehouse orders into memory. You can at least avoid that if you'll use Queryable.Any to check condition on database side:
!ctx.WarehouseOrders.Any(o => o.OrderNo == a.order_num)
But that will do database query for each shop order. I assume that you can get required shop orders with single database query. E.g. you can do group join shop orders with warehouse orders and select only those which don't have matches. Something like:
from so in ctx.ShopOrders
join wo in ctx.WarehouseOrders on so.order_num equals wo.OrderNo into g
where !g.Any()
select so

How do I group my LINQ query correctly?

I am having an issue getting my LINQ query to output as I would like. I am unsure I am taking the right approach.
Tables:
I have two tables Contacts and Permissions with which I perform a LEFT OUTER JOIN.
Join Query:
from contact in Contacts
join permission in Permissions on contact.Id equals permission.ObjectId into permissionGrp
from p in permissionGrp.DefaultIfEmpty()
where (p==null && isAllowed) || (p!=null && /* ... further conditions */))
orderby /* ... ordering removed */
select new { contact, permission = p };
This matches the permissions to a contact where applicable, and null when no matching permission exists.
Desired
I don't wish to have duplicate contacts, I am only interested in the first Contact-Permission record. Like so:
Attempt:
So I assumed that I need to Group By my contact.Id and somehow select FirstOrDefault() on the permissions collection.
from contact in Contacts
join permission in Permissions on contact.Id equals permission.ObjectId into permissionGrp
from p in permissionGrp.DefaultIfEmpty()
where (p==null && isAllowed) || (p!=null && /* ... further conditions */))
orderby /* ... ordering removed */
group p by contact into contactPermissionsGrp
select new { contact = contactPermissionsGrp.Key, permission = contactPermissions.FirstOrDefault() };
Result:
Unfortunately this results in a NotSupportedException: Specific method is not supported.. But I am not sure if my approach is correct or a limitation of the LightSpeed ORM.
Any advise would be appreciated.
Answer question with more questions
Is your query possible in raw SQL in the database you are targeting? If the answer is No then what hope have you of replicating it in LINQ?
I personally don't think that what you are trying to achieve is possible to do via LINQ against MySQL. It would be possible in MS SQL in raw T-SQL by defining an expression and attaching a RANK() column to it then doing a query on that expression.
I feel that your available solutions are:
Find out how to write this query using raw SQL in your native dialect. Lightspeed will let you execute raw SQL and it will even (where you return enough columns) rehydrate that custom query into Entitys (however I don't think that is what you are after in this case).
Give up on reducing the "duplicates" efficiently in the database. Pull the duplicates into memory and then reduce them in memory with LINQ queryies against the IEnumerable set that you get back.
Change your database architecture so you can have a simpler query. Sometimes in situations like this I will find honour in having a column on the Contact table such as "MostSignificantPermssion". That has a number of advantages:
Simpler query to get the Contact and the ONE significant Permission record.
Makes it more obvious to other developers that one of the Permissions has a special significance.
Options!
Appendix - Example of implementing (1) in MS SQL
WITH LastUsagePerPerson AS (
SELECT
ULE.PersonId,
ULE.[Device],
ULE.[AppVersion],
ULE.[CreatedOn],
ROW_NUMBER() OVER(PARTITION BY ULE.PersonId ORDER BY ULE.CreatedOn DESC) AS rk
FROM [dbo].[UsageLogEntry] ULE
)
SELECT
[FirstName]
,[LastName]
,[EmailAddress]
,[EmailAddressUnverified]
,[MobileNumber]
,[MobileNumberUnverified]
,[LastDeviceUsed] = LastUsagePerPerson.Device
,[LastAppVersion] = LastUsagePerPerson.AppVersion
,[LastDeviceUsage] = LastUsagePerPerson.CreatedOn
,[LastLoggedInOn]
FROM [dbo].[Person] P
LEFT JOIN LastUsagePerPerson ON P.Id = LastUsagePerPerson.PersonId
WHERE rk = 1
ORDER BY [Id]
I don't know what Lightspeed can or can't. Try to simplify you LINQ Query
In EF i would do something like this.
from c in Contacts
let p = (from p in permission where p.ObjectId == c.Id select p).FirstOrDefault()
select new { ContactID = c.Id,
Name = c.Name,
Permission = p.PermissionId,
Permitted = p.Permitted};
I have understood what you are trying to get and I have solved your problem,just follow the below code what I did...
select * from contacts as a
left join permissions as b
on a.ContactId = b.ContactId
group by a.ContactId ;
I have got the requeried result using the above code which you were trying to get.Just try that,your problem will be solved.

Linq to Entities many to many selection: How to force the generation of a JOIN instead of a subselect clause?

Using EF DB first I have two entities (Supplier, Product) that have a many-to-many relationship. Entity Framework does not create an entity for the associated table (SupplierProduct) as the associated table contains only the primary keys of the strong entities.
I have been getting all Suppliers that do not supply a given product with the following query:
var q1 = context.Suppliers.Where(s=>!s.Products.Any(p=>p.Id == 1));
The SQL produced uses an EXISTS dependent subquery similar to this:
SELECT *
FROM Suppliers s
WHERE NOT EXISTS
(SELECT 1
FROM SupplierProduct sp WHERE sp.SupplierId = s.Id && sp.ProductId = 1)
Is it possible, using Linq to Entities method syntax, to produce a query that uses joins on the associated table instead?
ie:
SELECT DISTINCT s.*
FROM SupplierProduct sp
JOIN Supplier s ON s.Id = sp.SupplierId;
WHERE sp.ProductId != 1
Update
As pointed out by JoeEnos my queries above don't do the same thing. The NOT EXISTS subquery is probably the best way to go here. What if I was trying to get all suppliers who did supply a product? I would change my linq to entities query slightly to:
var q1 = context.Suppliers.Where(s => s.Products.Any(p=>p.Id == 1));
And the SQL generated would be:
SELECT *
FROM Suppliers s
WHERE EXISTS
(SELECT 1
FROM SupplierProduct sp WHERE sp.SupplierId = s.Id && sp.ProductId = 1)
Which is fine, I get the result I want. However if I was writing SQL in this case I would normally do:
SELECT s.*
FROM SupplierProduct sp
JOIN Supplier s ON s.Id = sp.SupplierId;
WHERE sp.ProductId = 1
Can my linq to entities query be changed to produce the above SQL?
To generate SQL where a join is used instead of EXISTS when selecting an entity based on its m:n association with another entity SelectMany() can be used. Eg:
var q1 = context.Suppliers.Where(s => s.Products.Any(p=>p.Id == 1));
Can be rewritten to:
var q1 = context.Products.Where(p => p.Id == 1).SelectMany(p => p.Suppliers);
Your two queries do very different things. Your Any/EXISTS query gets suppliers who do not have product 1 at all. Your JOIN query gets all suppliers who have any products other than 1, regardless of whether or not they also have product 1.
I don't think you can do what you're looking for with just a JOIN and WHERE - you can do it with an IN clause, but I think the EXISTS query is the most correct way of looking for your data.
In any case, one of the wonderful things about Entity Framework is that you don't have to worry about what gets generated - as long as the LINQ statement is ok, then it will find the best way of writing the query, and you should never have to look at it. That's especially true when you do paging and other things like that, where the LINQ is simple, but the generated SQL is horribly ugly.

SQLCE: How to join tables from different SQLCE databases programmatically in C#?

I keep tables on different .sdf files because it's easy to manage them, ie; back up only changed db file, etc, plus in future db size might bigger and there is -4GB limit-
I need to join the tables and this will be my first -possibly LINQ- attempt. I know there are tons of examples/documents but a simple example would be nice to start.
This is the query for MS SQL Server:
SELECT personID, personPin, personName, seenTime
FROM db1.personList
LEFT JOIN db2.personAttendances on personID = seenPersonID
ORDER BY seenTime DESC
I think LINQ will be the way to go as you're querying across 2 different contexts. LINQ joins are quite easy: http://msdn.microsoft.com/en-gb/vcsharp/ee908647
Something like:
var q = from c in db1Context.personList
join p in db2Context.personAttendances on c.personID equals p.seenPersonID
select new { Category = c, p.ProductName };
I don't think SqlCE supports linking at the Db (SQL) level.
That means you'll have to use Linq-to-Objects. The example query has no WHERE clause so you can simply load the entire tables into Lists. But when the datasets get bigger that may not be acceptable.

Categories