Using 'OR' inside a LinQ join query (adapting SQL into LinQ) - c#

I have a SQL query that basically joins the MyWords table to the MyTranslations table on two keys. Here are my tables for better understanding.
MyWords table:
Id
WordString
LangType
MyTranslations table:
Id
WordColumnAId
WordColumnBId
Please note that WordColumnAIdand WordColumnBId columns are FKs that represents the MyWords.Id.
My SQL query:
SELECT MyTranslations.Id
,WordColumnAId
,WordColumnBId
,MyWords.WordString
,MyWords.LangType
FROM MyTranslations
join MyWords on (MyTranslations.WordColumnAId = MyWords.Id or MyTranslations.WordColumnBId = MyWords.Id)
where MyWords.LangType !=#currentLangType
I know it doesn't make sense to use join on with multiple keys at first glance but I'm trying to a cross-query that would join two tables whether the key is on WordColumnAId or WordColumnBId.
Problem
I'm trying to adapt the above T-SQL query into a LinQ query. The problem is that I can't find my way around LinQ to use two keys in a single join query.
Here's what I've got so far:
from translation in queryableTranslation
join word in _myWordRepository on translation.WordColumnAId equals word.Id // This is where I want to add `or translation.WordColumnBId equals word.Id` but get errors.
where word.LangType != currentLangType
select new QueryResultDto {
MyTranslationId = translation.Id,
WordString = word.WordString,
LanguageType = word.LangType,
WordColumnAId = translation.WordColumnAId,
WordColumnbId=translation.WordColumnbId,
};
I'm very new to the LinQ and trying to learn.
So my question: is there a way to achieve this in LinQ or am I trying the impossible? I'm also open to better approaches.

EF and other LINQ providers should translate query to INNER JOIN when using this syntax:
var query =
from translation in queryableTranslation
from word in _myWordRepository.Where(word => translation.WordColumnAId == word.Id
|| translation.WordColumnBId = word.Id)
where word.LangType != currentLangType
select new QueryResultDto
{
MyTranslationId = translation.Id,
WordString = word.WordString,
LanguageType = word.LangType,
WordColumnAId = translation.WordColumnAId,
WordColumnbId=translation.WordColumnbId,
};

Related

Is that possible to return a whole join table data to datagridview instead of specifying the item one by one?

I am trying to get all data from the join table to data review, but what I learn is just to specify the attributes one by one in the SELECT statement as following code:
var query = (from inv in db.tblinventories
join sup in db.tblsuppliers on inv.SupplierID equals sup.SupID into left
from sup in left.DefaultIfEmpty()
select new { inv.Invnum,inv.Model, sup.name }).ToList();
this.dgvPOS.DataSource = query;```
Is this the only way to fetch all data? Because in ORACLE SQL the way is quite simple by using "*" to represent all attributes like this:
SELECT *
FROM tblinventories
LEFT JOIN tblsuppliers
ON tblinventories.SupplierID = tblsuppliers.SupID;

SQL: Nested query does not have appropriate key

In LINQ, I am trying to inner join custom function written for full-text search and an Iqueryable result.
However, I get the following error when I try to to_ret.select(--something--).ToList()
Nested query does not have appropriate key
LINQ Code:
var sql_query = db.search(st);
var to_ret = from ts in sql_query
from t in table
where t.Id == ts.Value select t;
to_ret = to_ret.Include(x => x.table1)
.Include(x=> x.table2.Select(y=> y.table2Col));
to_ret.select(-something-).toList();
SQL Code:
create function [dbo].[search]
(#keywords nvarchar(4000))
returns table
as
return (
select [key] from containstable(tb,(Name,Description),#keywords)
)
Code that works in place of above LINQ Code :
var ids = (from t in table join ts in db.search(st) on t.Id equals ts.Value select t.Id).ToList();
to_ret = to_ret.Where(x => ids.Contains(x.Id));
However, the code that works isn't efficient enough as it eagerly loads all the ids for comparison
Do not join the table using LINQ, it is not effective.
You need to include all the joined functions into [dbo].[search] table valued function (like a view). Then do just call the [dbo].[search] from EF and filter it.
I have mentioned joined Fulltext table valued function here.
Note that fulltext and filtering together in one query could take time, because it is not easy job for query optimizer. Query optimizer selects to perform first fulltext on entire table(s) and then filtering or the opposite way.

Linq Multiple Joins

I have some sql tables that I need to query information from my current query that returns a single column list is:
from f in FactSales
where f.DateKey == 20130921
where f.CompanyID <= 1
join item in DimMenuItems
on f.MenuItemKey equals item.MenuItemKey
join dmi in DimMenuItemDepts
on item.MenuItemDeptKey equals dmi.MenuItemDeptKey
group f by dmi.MenuItemDeptKey into c
select new {
Amount = c.Sum(l=>l.Amount)
}
This returns the data I want and it groups correctly by the third table I join but I cannot get the Description column from the dmi table. I have tried to add the field
Description = dmi.Description
but it doesnt work. How can I get data from the third table into the new select that I am creating with this statement? Many thanks for any help.
Firstly you are using Entity Framework COMPLETELY WRONG. Linq is NOT SQL.
You shouldn't be using join. Instead you should be using Associations.
So instead, your query should look like...
from sale in FactSales
where sale.DateKey == 20130921
where sale.CompanyID <= 1
group sale by sale.Item.Department into c
select new
{
Amount = c.Sum(l => l.Amount)
Department = c.Key
}
By following Associations, you will automatically be implicitly joining.
You should not be grouping by the id of the "table" but by the actual "row", or in Object parlance (which is what you should be using in EF, since the raison d'etre of an ORM is to convert DB to Object), is that you should be grouping by the "entity" rather than they the "entity's key".
EF already knows that the key is unique to the entity.
The grouping key word only allows you to access sale and sale.Item.Department after it. It is a transform, rather than an operator like in SQL.

EF (LINQ to SQL) - How to query?

I have the concept of a document that has keyword/s. EF abstracted out the document-keyword joining table to an association.
The structure looks like this
Document: ID (PK)
Document_Keyword: DocumentID (PK), Keyword (PK)
Keyword: Keyword (PK)
I have the requirement to return a list of documents where they contain ALL keywords in a string[]
If I was doing this in SQL it would be similar to below
with t as (
select 'keyword1' KEYWORD union
select 'keyword2'
)
select DocumentID,count(*) from [dbo].[Document_Keyword] p
inner join t on p.KEYWORD = t.KEYWORD
group by DocumentID
having count(*) = (select count(*) from t)
Im struggling to form a linq query that will give me the same result.
I have tried the following LINQ statement however it does returns documents that contain 1 or more of the keywords in the array. I require that documents are only returned if ALL keywords match.
var query = (from k in db.KEYWORD
from b in k.DOCUMENT
join q in arrKeywords //array of string[]
on k.KEYWORD equals q
select new Document()
{
Filename = b.FILENAME,
Description = b.TITLE
});
Any ideas?
Cheers
Jeremy
If I get you well you want entries of which all keywords match exactly, i.e. it doesn't have any other keywords. A way too achieve this is
var kwc = arrKeywords.Count();
var query = from k in db.KEYWORD
let kw = k.DOCUMENT.Select(d => d.KEYWORD)
where kw.All(kw1 => arrKeywords.Contains(kw1))
&& kw.Count() == kwc;
The generated query is still much longer than a hand-coded one would be, but I think the database's query optimizer should be able to handle this.

Linq Join variable scoping issue

Really odd issue that I cant work out.
I am trying to join two tables in a linq statement to only retrieve records where the record in table 1 has no related rows in table 2.
I have used Joins before but for some reason I cant get VS to recognise the second table in the linq statement.
EG.
var result =
(from pc in _dataSource.Payments
join bc in _dataSource.BouncedCheques
on pc.PaymentID != bc.PaymentID //This is where the error occurs, VS does not recognise "bc"
where pc.CustomerNumber == getAccountNumber
& pc.IsDeleted == false
orderby pc.PaymentDate descending
select new PaymentAllocation
{
PaymentId = pc.PaymentID,
PaymentDate = pc.PaymentDate,
CustomerNumber = pc.CustomerNumber,
ChequeReference = pc.ChequeReference,
PaymentValue = pc.PaymentValue,
AllocatedValue = pc.AllocatedValue,
UnallocatedValue = pc.PaymentValue - pc.AllocatedValue,
ReceivedBy = pc.ReceivedBy,
PaymentType = pc.PaymentType,
PostedDate = pc.PostedDate
});
Basically the problem is that the variable "bc" does not seem to be recognised, however I have several other similar Linq queries that all work well
Any ideas?
Your problem is that the syntax for join uses the keyword equals and not standard boolean operators.
Try replacing your join by a cartesian product of your tables:
from pc in _dataSource.Payments
from bc in _dataSource.BouncedCheques
where
pc.PaymentID != bc.PaymentID
&& pc.CustomerNumber == getAccountNumber
& pc.IsDeleted == false
In the join clause you should use the equals keyword:
try:
on pc.PaymentID equals bc.PaymentID

Categories

Resources