linq query with condition - c#

I'm writing a linq query in query syntax and I'm wondering how to add another where clause.
Basically, I have the following:
var test = from t in MyDC.TheTable
where t.UserID == TheUserID
where t.DateDone.Date == TheDate.Date
select new MyModel {.....};
TheTable has a column called LinkedID and this column is also in another table called ColorStatus (a number between 1 and 10). I'm looking to write the where clause "where the LinkedID in the ColorStatus table is less than 7".
Thanks.

Just a suggestion on improving the statement you have. You can actually merge the two where conditions into a single one. && means "AND"
Where t.UserID == TheUserID && t.DateDone.Date = TheDate.Date

Your information "another table called ColorStatus" doesn't make sense here.
var test = from t in MyDC.TheTable
where t.UserID == TheUserID
&& t.DateDone.Date == TheDate.Date
&& t.LinkedID < 7
select new MyModel {.....};
Probably I didn't get your idea, here is an example of join may help you.
var test = from t in MyDC.TheTable
join x in MyDC.ColorStatus
on t.LinkedID == x.LinkedID
where t.UserID == TheUserID
&& t.DateDone.Date == TheDate.Date
&& x.AnotherField == 1
select new MyModel {.....};

Related

How do I write SELECT FROM myTable WHERE id = (SELECT) in Linq?

How can I rewrite this SQL query in LINQ with a lambda expression?
SELECT
CO.*
FROM
COMPANY CO
WHERE
CO.ID = '5'
AND CO.ID <> (SELECT COMPANY_ID
FROM dbo.EMPLOYEE
WHERE USERNAME = 'ADMIN')
I tried the following code I think it is correct, but it is not working:
var obj1 = db.COMPANies
.Where(co => co.ID != co.EMPLOYEEs.SingleOrDefault(em => em.USERNAME == userName).COMPANY_ID && co.ID == iID);
Can you please help me?
Can I use
co.EMPLOYEEs.SingleOrDefault(em => em.USERNAME == userName).COMPANY_ID
inside the db.COMPANies.Where ??
I have read the question in: How do I write SELECT FROM myTable WHERE id = (SELECT) in Linq?
but it not help me.
EDIT :
Image table structure, Click here
Sorry for my bad english. Thanks!
I hope that you have objects of COMPANY table and EMPLOYEE table which will be having the data. On those objects, you can fire the below LINQ to achieve your results.
COMPANY.Select(x => x.Id == 5 && x.Id != EMPLOYEE.Where(z => z.USERNAME == "ADMIN").Select(g => g.COMPANY_ID).FirstOrDefault());
Don't forget to add using System.Linq;
Using lambda expression, you can try this
var comapaniesWhereUserIsAdmin = from e in db.EMPLOYEEs
where e.username='Admin'
select e.CompanyId;
var result = from c in db.Companies
where c.ID == iID && !comapaniesWhereUserIsAdmin.Contains(c.ID)
select c;

How to write query in Entity Framework with conditional multiple where condition? [duplicate]

This question already has answers here:
Linq: adding conditions to the where clause conditionally
(9 answers)
Closed 3 years ago.
I am creating a wcf application which is connecting to DB to get some data for customer using Entity Framework. The concept is to search a customer based on the search parameters. User can provide all or few or at least one of the search parameters. But I am quite new in Entity Framework and getting confused on how to do this. I can do this in traditional SQL coding by considering If - Else condition in c# side.
This is my code which is getting the all of the paramters:
var customers = from o in natCustomer.CustomerLists
select o;
customers = customers.Where(c => c.Name == sName && c.Age == iAge
&& c.Gender == sGender && c.Height == dHeight && c.Weight == dWeight
&& c.Nationality == sNationality
&& c.EyeColor == sEyeColor && c.SpecialMark == sSpecialMark);
Please help me by suggesting how do I get the result with few or one parameter only.
Thanks
Entity Framework queries are "deferred" queries. They don't actually run until you start asking for results. This means you can build up a query in pieces and it will (mostly) work exactly like one bigger query.
In your case, you can do something like:
var customers = from o in natCustomer.CustomerLists
select o;
if (!string.isNullOrEmpty(sName))
customers = customers.Where(c => c.Name == sName);
if (!string.isNullOrEmpty(sNationality))
customers = customers.Where(c => c.sNationality == sNationality);
if (!string.isNullOrEmpty(SpecialMark ))
customers = customers.Where(c => c.SpecialMark == SpecialMark);
etc. At the end, when you execute the customers query (for example, call ToList or use a foreach loop) EF will consolidate all of those smaller Where clauses into a single SQL query to run against your data.
Assuming you only want to find customers who match on all non-null parameters, an alternative approach is to include the null checks within the where query, and only compare the parameter to the customer data if the parameter is not null.
customers = customers.Where(c => (string.isNullOrEmpty(sName) || c.Name == sName)
&& (iAge == null || c.Age == iAge)
&& (string.isNullOrEmpty(sGender) || c.Gender == sGender));
You need some way to determine if the given inputs are set or not. For a simplification I assume you receive your parameters as nullables. So you could add an additional condition, if the parameter is provided:
customers = sName == null ? customers : customers.Where(c => c.Name == sName);
customers = iAge == null ? customers : customers.Where(c => c.Age == iAge);
customers = sGender == null ? customers : customers.Where(c => c.Gender == sGender);
...

Writing the LINQ equaivalent of a SQL join

This is the SQL query I have written:
select * from Addresses a
join ProviderAddresses pa on a.address_k = pa.address_k
where pa.provider_k = 'ABC123'
and pa.active = 1
and a.active = 1
and pa.addresstype_rtk = 'HOME'
And this is the LINQ query I wrote for it:
public IQueryable<Addresses> GetAddressesesForProvider(string provider_k, string addresstype_rtk)
{
var query = from a in this.Context.Addresses
join pa in this.Context.ProviderAddresses on a.Address_K equals pa.Address_K
where pa.AddressType_RTK == addresstype_rtk
&& pa.Active == true
&& a.Active == true
select a;
return query;
}
But it is wrong. The LINQ one return thousands of records and the SQL one returns only one record.
It is IQueryable because later I need to go through its results with a for-each loop.
In the SQL I am passing hard coded values for testing but in my code for me LINQ method I also pass the same hard coded values so that is not the issue.
Looks like you may have just missed adding the provider_k condition to the where;
public IQueryable<Addresses> GetAddressesesForProvider(string provider_k, string addresstype_rtk)
{
var query = from a in this.Context.Addresses
join pa in this.Context.ProviderAddresses on a.Address_K equals pa.Address_K
where pa.Provider_K == provider_k &&
pa.AddressType_RTK == addresstype_rtk &&
pa.Active == true &&
a.Active == true
select a;
return query;
}

C# Entity Framework using class from model in a query slower than using anonymous class

I am using Entity Framework 5 to access my DB. The model is quite complex with a lot of navigation properties. I have written the following query using linq:
var myQuery =
from cp in context.ClosedPositions.Include("Position").Include("Position.Folder").Include("Position.Strategy").Include("Position.Symbol").Include("Position.StopTargetPlacer")
where cp.Position.EntryDate >= fromDT &&
cp.ExitDate <= toDT &&
(cp.Position.Folder.FolderCode == myFolder || showAllFolders) &&
(cp.Position.Strategy.Name == myStrategy || showAllStrategies) &&
(cp.Position.Symbol.Name == mySymbol || showAllSymbols) &&
(cp.Position.Symbol.Exchange == myExchange || showAllExchanges)
orderby cp.Position.EntryDate
select cp;
The navigations multiplicity are the following:
Position 1 - * ClosedPostion
Position * - 1 Folder
Position * - 1 Strategy
Position * - 1 Symbol
Then in a foreach query I use the Data from the Included navigation properties. I think this way should not hit the database more than once. The query runs for about 6 seconds.
Then I have rewritten the query to this:
var myQuery =
from cp in context.ClosedPositions
join p in context.Positions on cp.PositionID equals p.ID
join f in context.Folders on p.FolderID equals f.ID
join sy in context.Symbols on p.SymbolID equals sy.ID
join st in context.Strategies on p.StrategyID equals st.ID
join stp in context.StopTargetPlacers on p.StopTargetPlacerID equals stp.ID
where p.EntryDate >= fromDT &&
cp.ExitDate <= toDT &&
(f.FolderCode == myFolder || showAllFolders) &&
(st.Name == myStrategy || showAllStrategies) &&
(sy.Name == mySymbol || showAllSymbols) &&
(sy.Exchange == myExchange || showAllExchanges)
orderby p.EntryDate
select new
{
ClosedPositionID = cp.ID,
PositionID = p.ID,
p.EntryChartID,
cp.ExitChartID,
p.EntryDate,
cp.ExitDate,
Symbol = sy.Name,
Strategy = st.Name,
p.Size,
cp.Profit,
STPlacer = p.StopTargetPlacer.Name,
InitialRisk = p.InitialRisk,
StrategyDirection = st.Direction
};
Again I have used the same foreach loop to work on the data. This time the total processing time was only around 1 second.
I have examined the generated SQL queries by both LINQ query in running them in the SSMS both of them returned the same data in the same amount of time.
My question is why is there the huge delay between using an anonymous class and a class from the model of the context?
Ok after some research I found out that the problem is that in the first case in the background the EF builds up the change tracking structure and in the second case since I am using an anonymous class this will not happen. The solution was the AsNoTracking function:
var myQuery =
from cp in context.ClosedPositions.Include("Position").AsNoTracking().Include("Position.Folder").Include("Position.Strategy").Include("Position.Symbol").Include("Position.StopTargetPlacer")
where cp.Position.EntryDate >= fromDT &&
cp.ExitDate <= toDT &&
(cp.Position.Folder.FolderCode == myFolder || showAllFolders) &&
(cp.Position.Strategy.Name == myStrategy || showAllStrategies) &&
(cp.Position.Symbol.Name == mySymbol || showAllSymbols) &&
(cp.Position.Symbol.Exchange == myExchange || showAllExchanges)
orderby cp.Position.EntryDate
select cp;
How many records are we talking about?
Have you disabled Entity Tracking at the context level?
Remember that when EF materializes an entity with tracking enabled it has to check every record coming from the database to make sure it does not materialize the same object again. Also tracking an entity is more expensive because it has to register all the entities (more code execution).
When you materialize an anonymous type the context does not worry about all this.
Looks to me like the first query is going to basically pull back every property on the entities that are used in the navigation properties even if you don't want them and the second query is using projection so its only going to retrieve those properties you have specifically asked for in your query... in this instance only the Strategy name for example and ignores everything else that may belong to a strategy.
Although this is over simplified... imagine the following scenario... (MyTable has X number of columns)
First Query is much like:
SELECT * FROM MyTable
Where as projection enables EF to be alot more specific...
SELECT column1, column2, column3 FROM MyTable
And that is why you are experiencing a much faster query.

How can i use in ( select method in linq?

how can i write "in( select" method in linq?
I'm trying to convert :
UPDATE ActualAmountsByLocation SET isCustomerItem=1 WHERE ItemBarcode IN (SELECT barcode FROM StockMaterials WHERE barcode=#Barcode AND ownership=1)
I've tried like this:
Array stockMaterials = ( from s in stockMovementCtx.StockMaterials where s.barcode == Barcode && s.ownership ==1 select s).ToArray();
actualAmountsByLocation = (from a in stockMovementCtx.ActualAmountsByLocations
where a.ItemBarcode.Contains(stockMaterials)
select a).First();
To get an IN query you need to reverse the sense of the contains. Also, no need to materialize the first query, IMO.
var stockMaterials = from s in stockMovementCtx.StockMaterials
where s.barcode == Barcode && s.ownership ==1
select s;
actualAmountsByLocation = (from a in stockMovementCtx.ActualAmountsByLocations
where stockMaterials.Contains( a.ItemBarcode)
select a).First();
You're almost there.
Remove the .ToArray call to prevent the query from being executed directly, and make your stockMaterials variable of type IQueryable<StockMaterial>.
This what you're looking for?
ActualAmountsByLocation = StockMaterials.Where(s => s.barcode == Barcode && s.ownership == 1).ToArray();
var stockMaterials = (from s in stockMovementCtx.StockMaterials
where s.barcode == Barcode && s.ownership == 1
select s).ToArray();
var actualAmountsByLocation = (from a in stockMovementCtx.ActualAmountsByLocations
where stockMaterials.Contains(a.ItemBarcode)
select a).First();
Hopefully this code example below is helpful for you
// these are using linq methods
var barcodes = stockMovementCtx.StockMaterials
.Where(s => s.barcode == Barcode && s.ownership == 1)
.Select(s => s.barcode);
var amounts = stockMovementCtx.ActualAmountsByLocations
.Where(a => barcodes.Contains(a.ItemBarCode))
.FirstOrDefault();
// if you would like to use the query expressions instead, here they are
//var barcodes = from s in stockMovementCtx.StockMaterials
// where s.barcode = Barcode && s.ownership == 1
// select s.barcode;
//var amounts = (from a in stockMovementCtx.ActualAmountsByLocations
// where barcodes.Contains(a.ItemBarCode.Contains)
// select a).FirstOrDefault();
// helpful to use FirstOrDefault if you are not sure that the query will return a result
if (amounts != null) {
// change value
amounts.IsCustomerItem = 1;
// update database
stockMovementCtx.SubmitChanges();
}
Making update on LinQ is so easy thing, check the code block below for example.
var user = (from s in dataContext.USERS
Calling Users Table, and setting where condition.
where s.UserId.Equals(id)
select s).FirstOrDefault();
I want to make change on user email.(Dont forget this: If you call with ToList(), you need to control list count to avoid exception for ex: if(user.Count > 0)..)
Updating user:
s.EmailAddress = serkan#serkanhekimoglu.com;
dataContext.SubmitChanges();
and your data will be updated after SubmitChanges();

Categories

Resources