How to set Filter Values in LinQ with SQL Query Text? - linq

I am using LINQ for my database application.
So I can write things like:
using (ShuttleDataContext dc = Config.GetNewShuttleDBConnection())
{
List<RefState> states = (from a in dc.RefStates select a).ToList();
return states;
}
Know I have to handle the requierement, that I have to filter from this database by SQL strings, e.g. a filter string: "ID like '7%'" or "Name = 'Red'".
Of course normaly I would write something like .Where(a => a.Name == "Red"), but it's nearly impossible to map every filterexpression to a where clause... So is there a method to have native T-SQL in an Linq-List?

As far as I know you can't just provide the filter condition, but you can use ExecuteQuery to execute an arbitrary SQL statement and map that to your LINQ types:
List<RefState> states = dc.ExecuteQuery<RefState>(
"SELECT * FROM RefStates WHERE ID LIKE '7%'").ToList();

Related

Dynamic Linq on DataTable error: no Field or Property in DataRow, c#

I have some errors using Linq on DataTable and I couldn't figure it out how to solve it. I have to admit that i am pretty new to Linq and I searched the forum and Internet and couldn't figure it out. hope you can help.
I have a DataTable called campaign with three columns: ID (int), Product (string), Channel (string). The DataTable is already filled with data. I am trying to select a subset of the campaign records which satisfied the conditions selected by the end user. For example, the user want to list only if the Product is either 'EWH' or 'HEC'. The selection criteria is dynaically determined by the end user.
I have the following C# code:
private void btnClick()
{
IEnumerable<DataRow> query =
from zz in campaign.AsEnumerable()
orderby zz.Field<string>("ID")
select zz;
string whereClause = "zz.Field<string>(\"Product\") in ('EWH','HEC')";
query = query.Where(whereClause);
DataTable sublist = query.CopyToDataTable<DataRow>();
}
But it gives me an error on line: query = query.Where(whereClause), saying
No property or field 'zz' exists in type 'DataRow'".
If I changed to:
string whereClause = "Product in ('EWH','HEC')"; it will say:
No property or field 'Product' exists in type 'DataRow'
Can anyone help me on how to solve this problem? I feel it could be a pretty simple syntax change, but I just don't know at this time.
First, this line has an error
orderby zz.Field<string>("ID")
because as you said, your ID column is of type int.
Second, you need to learn LINQ query syntax. Forget about strings, the same way you used from, orderby, select in the query, you can also use where and many other operators. Also you'll need to learn the equivalent LINQ constructs for SQL-ish things, like for instance IN (...) is mapped to Enumerable.Contains etc.
With all that being said, here is your query
var productFilter = new[] { "EWH", "HEC" };
var query =
from zz in campaign.AsEnumerable()
where productFilter.Contains(zz.Field<string>("Product"))
orderby zz.Field<int>("ID")
select zz;
Update As per your comment, if you want to make this dynamic, then you need to switch to lambda syntax. Multiple and criteria can be composed by chaining multiple Where clauses like this
List<string> productFilter = ...; // coming from outside
List<string> channelFilter = ...; // coming from outside
var query = campaign.AsEnumerable();
// Apply filters if needed
if (productFilter != null && productFilter.Count > 0)
query = query.Where(zz => productFilter.Contains(zz.Field<string>("Product")));
if (channelFilter != null && channelFilter.Count > 0)
query = query.Where(zz => channelFilter.Contains(zz.Field<string>("Channel")));
// Once finished with filtering, do the ordering
query = query.OrderBy(zz => zz.Field<int>("ID"));

How to get the Entity-SQL command text by LINQ query?

It's an exercise of EF code-first. There's a simple method. I want to get the Entity SQL command text generated by object services.
(MyDbContext is derived form DbContext. Person is a POCO class.)
using (MyDbContext context = new MyDbContext())
{
var query = context.Set<Person>().FirstOrDefault(p => p.Age == 1);
Console.WriteLine(query.Name);
var objquery = query as ObjectQuery;
if (objquery != null)
Console.WriteLine(objquery.CommandText);
}
I used to get native SQL command text by ObjectQuery.TraceString in LINQ to Entity. Now, what I need is Entity-SQL statement, NOT native SQL statement.
But, I can't cast the query from IQueryable<Person> to ObjectQuery or ObjectQuery<Person>.
I tried to get members of DbQuery by reflection. It seems that DbQuery hasn't any property about command text or trace string.
Thanks
My suggestion for what you want is using Dynamic Linq. The library (part of the Linq Samples) includes many IQueryable extensions that return Linq.DataQuery objects. Once you consume the DataQuery you'll have the expected object.
var testQuery =
db.Cases.
Where("KeyID > 1").
Take(1);
foreach (var r in testQuery)
{
Console.WriteLine(r);
}
Then, you can check against your query as such.
testQuery.Expression
testQuery.Provider
These will give you:
{Table(Case).Where( => (.Keyid > 1)).Take(1)}
System.Linq.Expressions.Expression {System.Linq.Expressions.MethodCallExpression}
-and-
{SELECT TOP (1) [t0].[Keyid], [t0].[FileNo], [t0].[MatterType], [t0].[LoanNo], [t0].[Investor], [t0].[LoanType], [t0].[Client], [t0].[ClientFileNo], [t0].[ClientStatus], [t0].[Mortgagor], [t0].[County], [t0].[PropertyStreet1], [t0].[PropertyStreet2], [t0].[PropertyCity], [t0].[PropertyState], [t0].[PropertyZipcode], [t0].[Status], [t0].[BoxNo], [t0].[InsurerLoanno], [t0].[InvestorLoanno], [t0].[insurer_name_id], [t0].[OldSystemKey], [t0].[FinalBilling], [t0].[HoldBilling], [t0].[LastModified], [t0].[PiggyLoanNo], [t0].[CurrComentID], [t0].[LockEFILE], [t0].[MSJAmount], [t0].[Created], [t0].[Locked], [t0].[FinalBillingDate], [t0].[HoldBillingDate], [t0].[CreatedBy], [t0].[Stage], [t0].[PriorStage], [t0].[DefendantUpdated], [t0].[VestingCode], [t0].[FileSource], [t0].[SubVestingCode], [t0].[AttorneyAssigment], [t0].[VoluntarySurrender], [t0].[FNMARisk], [t0].[Source], [t0].[REO_ID], [t0].[WTI_ID], [t0].[CaseDismissed], [t0].[REO_CompanyID], [t0].[SubMattertype], [t0].[VendorCode], [t0].[SubType]
FROM [dbo].[Cases] AS [t0]
WHERE [t0].[Keyid] > #p0}
System.Linq.IQueryProvider {System.Data.Linq.DataQuery<CMSDEVMapping.Case>}
You can also verify your type in the loop:
r.GetType() {Name = "Case" FullName = "CMSDEVMapping.Case"} System.Type {System.RuntimeType}

Nhibernate linq. The where extension method does not add the where clause to the SQL command, why?

I want to add the where clause to a linq statement, but it doesn't behave as i would expected it to.
When i use this code:
IQueryable<Employee> EmpQuery = from e in Session.Query<Employee>() where e.Surname == "Test" select e;
EmpQuery.ToList();
or i use this code:
IQueryable<Employee> EmpQuery = (from e in Session.Query<Employee>() select e).Where(e => e.Surname == "Test");
EmpQuery.ToList();
The where clause is included in the SQL command, but when i try it this way:
IQueryable<Employee> EmpQuery = from e in Session.Query<Employee>() select e;
EmpQuery.Where(e => e.Surname == "Test");
The where clause is not included in the SQL command. Why is this? Is there another way to dynamically add criteria to a Nhibernate Linq query?
You're not using the return value of Where. LINQ is designed around functional concepts - calling Where doesn't modify the existing query, it returns a new query which applies the filter. The existing query remains as it was - which means you can reuse it for (say) a different filter.
Note that your current query expression (from x in y select x, effectively) is pretty pointless. I would suggest simply writing:
var query = Session.Query<Employee>().Where(e => e.Surname == "Test");
Just to clarify on Jon's remark, your implementation would be fine with the following tweak:
IQueryable<Employee> modifiedQuery = EmpQuery.Where(e => e.Surname == "Test");
Then just invoke the appropriate enumerator (ToList, ToArray, foreach) on modifiedQuery. And I wouldn't say that it create a complete new query, but instead creates a query which wraps around the original (kind of along the lines of the adapter pattern). Granted, your example doesn't need the additions, but this is how you would add additional criteria onto an existing LINQ expression, and that is what your question actually asked.

How do I use Like in Linq Query?

How I can use Like query in LINQ ....
in sql for eg..
name like='apple';
thanks..
Use normal .NET methods. For example:
var query = from person in people
where person.Name.StartsWith("apple") // equivalent to LIKE 'apple%'
select person;
(Or EndsWith, or Contains.) LINQ to SQL will translate these into the appropriate SQL.
This will work in dot notation as well - there's nothing magic about query expressions:
// Will find New York
var query = cities.Where(city => city.Name.EndsWith("York"));
You need to use StartsWith, Contains or EndsWith depending on where your string can appear. For example:
var query = from c in ctx.Customers
where c.City.StartsWith("Lo")
select c;
will find all cities that start with "Lo" (e.g. London).
var query = from c in ctx.Customers
where c.City.Contains("York")
select c;
will find all cities that contain "York" (e.g. New York, Yorktown)
Source
name.contains("apple");
I use item.Contains("criteria"), but, it works efficiently only if you convert to lower both, criteria and item like this:
string criteria = txtSearchItemCriteria.Text.ToLower();
IEnumerable<Item> result = items.Where(x => x.Name.ToLower().Contains(criteria));

Is there a pattern using Linq to dynamically create a filter?

Is there a pattern using Linq to dynamically create a filter?
I have the need to create custom filtering on a list, in the past I would just dynamically create the SQL...it doesn't seem like this is possible with Linq.
Check out the Dynamic Linq Library from ScottGu's blog:
For example, below is a standard type-safe LINQ to SQL VB query that retrieves data from a Northwind database and displays it in a ASP.NET GridView control:
Dim Northwind As New NorthwindDataContext
Dim query = From q In Northwind.Products Where p.CategoryID = 2 And p.UnitPrice > 3 Order By p.SupplierID Select p
Gridview1.DataSource = query
GridView1.DataBind()
Using the LINQ DynamicQuery library I could re-write the above query expression instead like so
Dim Northwind As New NorthwindDataContext
Dim query = Northwind.Products .where("CategoryID=2 And UnitPrice>3") . OrderBy("SupplierId")
Gridview1.DataSource = query
GridView1.DataBind()
Notice how the conditional-where clause and sort-orderby clause now take string expressions instead of code expressions. Because they are late-bound strings I can dynamically construct them. For example: I could provide UI to an end-user business analyst using my application that enables them to construct queries on their own (including arbitrary conditional clauses).
Dynamic Linq is one way to go.
It may be overkill for your scenario. Consider:
IQueryable<Customer> query = db.Customers;
if (searchingByName)
{
query = query.Where(c => c.Name.StartsWith(someletters));
}
if (searchingById)
{
query = query.Where(c => c.Id == Id);
}
if (searchingByDonuts)
{
query = query.Where(c => c.Donuts.Any(d => !d.IsEaten));
}
query = query.OrderBy(c => c.Name);
List<Customer> = query.Take(10).ToList();
Dynamically Composing Expression Predicates
something like this?
var myList = new List<string> { "a","b","c" };
var items = from item in db.Items
where myList.Contains(item.Name)
select item;
that would create a sql statement like
SELECT * FROM Items [t0] where Name IN ('a','b','c')

Resources