LINQ query in C# using string on the fly to ORDER data - c#

I have a function with two strings. Can't figure out how to incorporate those two strings into a LINQ query.
Here is my function:
private void DataBind_GridView_Search(string OptionalArgsSortExpression = "", string OptionalArgsSortDirection = "")
{
List<mainSearchDataModel> Query = GetData();
if (Query != null)
{
/* Problem ... */
Query = from x in Query
orderby OptionalArgsSortExpression.ToString() OptionalArgsSortDirection.ToString()
select x;
/* Problem ... */
GridView_Search.DataSource = Query;
GridView_Search.DataBind();
}
Any comments would be highly appreciated.
This is the error I get. Also I am not using DLINQ.
'System.Linq.Enumerable.OrderBy(System.Collections.Generic.IEnumerable, System.Func)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
UPDATE:
Is there a way to ORDER a List or IEnumerable either one. It seems everything I try does not work.
There is a way to convert it to DataView but I run into trouble there as well and would rather not go that way.

You could try something like this (Provided that you use DLINQ, as Servy pointed out in his comment.):
var query = query.OrderBy(String.Format("{0} {1}",OptionalArgsSortExpression,OptionalArgsSortDirection));

You could use my OrderByString extension. It converts strings into calls to the actual OrderBy methods, so it is compatible with all Linq providers.
using OrderByExtensions;
Query = Query.OrderBy(OptionalArgsSortExpression.ToString()
+ " " + OptionalArgsSortDirection.ToString())
https://github.com/Grax32/OrderByString
https://www.nuget.org/packages/OrderByString/

You could go this route
GridView.DataSource = Query.OrderBy(o => o.Field1).ThenBy(t => t.Field2).ToList()

Related

Formatting Select Statement Using Dynamic Linq

I've been looking into this for quite some time now and cannot figure out a resolution. I Originally Tried formatting A dynamic linq Statement as you can see here in this post
I declared a class:
public class DynamicHelper
{
public string FormattedLink(string DisplayText, string ID)
{
return "" + DisplayText + "";
}
public string FormattedLink(string DisplayText, int ID)
{
return "" + DisplayText + "";
}
}
After I inserted a new type in DynamicLinq into the predefinedTypes
,typeof(DynamicHelper) //around line 635
I have a program which is attempting to Invoke the FormattedLink inside of a dynamic linq select:
using (var Model = new MK3Entities())
{
DynamicHelper Dh = new DynamicHelper();
var TOrigin = (Model.Titles.Where("ID > 19632")
.Select("new(ID, #0.FormattedLink(ExtTitleID, ID) as ExtTitleID )", Dh) as System.Collections.IEnumerable)
.Cast<dynamic>().Take(10).ToList();
Console.ReadKey();
}
When I execute this program I get a runtime exception "LINQ to Entities does not recognize the method 'System.String FormattedLink(System.String, Int32)' method, and this method cannot be translated into a store expression."
Any Ideas on how to fix this... I just need simple formatting from Dynamic Select.
The error message is pretty self explanatory. The database doesn't know how to translate that method into SQL. You need to fetch the information that the method needs in your database query and then call that function on the results, rather than in the query.
I'm not sure why you need it to be dynamic, it seems the solution you present is very overly complicated. I would write it as:
using (var Model = new MK3Entities())
{
DynamicHelper Dh = new DynamicHelper();
var TOrigin = Model.Titles
.Where("ID > 19632")
.Select(t => new { ID = t.ID, ExtTitleID = t.ExtTitleId })
.Take(10)
.ToList() // Execute SQL Statement
.Select(t => new {ID = t.ID, Link = nh.FormattedLink(ExtTitleID, ID)})
.ToList();
Console.ReadKey();
}
I'm returning an List<anonymous'1> object instead of a dynamic object (because I've never had the need for dynamic objects) so you can adjust it accordingly.
I just solved similiar problem few hours back.
YOu need ToList() that works with Dynamic linq. Check out this thread: Can't find property or field on a dynamic object
Just copy paste those to your project, and later:
var TOrigin = (Model.Titles.Where("ID > 19632")
.ToAnonymousList()
.Select("new(ID, #0.FormattedLink(ExtTitleID, ID) as
ExtTitleID )", Dh) as System.Collections.IEnumerable);

How do I get SQL statement from LinqToEntities clause

I have an issue that's causing me a lot of headache. I've already googled a solution some days ago, but I didn't found it yet, if one of you guys could help me, it would be great!
I have this method to take the SQL statement for me:
private static string GetClause<T>(IQueryable<T> clause) where T : BaseEntity
{
string snippet = "FROM [dbo].[";
string sql = clause.ToString();
string sqlFirstPart = sql.Substring(sql.IndexOf(snippet));
sqlFirstPart = sqlFirstPart.Replace("AS [Extent1]", "");
sqlFirstPart = sqlFirstPart.Replace("[Extent1].", "");
return sqlFirstPart;
}
But this doesn't work when I try to use some filter (e.g. where), cause it returns me some ""#p_linq_{0}"." instead of the values. I know these are the parameters of my query, but where are they stored?
I use this for batch delete purposes on the EF5 Code First.
If you create a query with a param like this:
var name = "xxx";
var query = ctx.Persons.Where(x => x.FirstName == name);
Then you can get the sql statement and parameters like this:
var oq = ((ObjectQuery<Person>)query);
var trace = oq.ToTraceString();
var p = oq.Parameters;
Use the param name "p_linq_{0}" without the # as an index on p, p["p_linq_{0}"].

Anonymous Type Appears in both Error

I have a linq query that populates the GridView on Page_Load. I have made a for loop of Characters for the alphabet. In the .Command of the LinkButton that populates the LinkButton, I am running a very similar query using the same parameters in the query and getting the below error.
The type '<>f__AnonymousType2' exists in both 'ConcernContracts.dll' and 'System.Web.WebPages.Deployment.dll'
void lnkCharacter_Command(object sender, CommandEventArgs e)
{
try
{
var lbtn = (LinkButton)lbl_Alphabet.FindControl("lnkCharacter" + e.CommandArgument);
var id = lbtn.Text;
using (var db = new dbDataContext())
{
var query = from n in db.tbl_Providers
where ((n.provider_Name.StartsWith(id)) && (n.provider_Deleted == false))
select new
{
n.ProviderId,
n.provider_Name
};
grd_Provider.DataSource = null;
grd_Provider.DataSource = query;
grd_Provider.DataBind();
}
}
catch (SystemException ex) { }
}
The LoadGrid() is the same, but it doesn't use the .StartsWith() condition.
Do you have any Ideas how to solve the error?
The error doesn't throw an exception, but it doesn't populate the grid for either of the queries. The error was discovered in the following line: grd_Provider.DataSource = query;
Change your grid data source
grd_Provider.DataSource = query.ToList();
grd_Provider.DataBind();
or create List having two properties Provider Id and Name and bind that list from output
like this.
List<Entities> abc=query.ToList();
grd_Provider.DataSource =abc;
grd_Provider.DataBind();
Here is a suggestion:
Your two similar queries are probably overlapping on that anonymous type you are selecting in the LINQ query. On one and only one of the queries, change the select new to look like this:
select new
{
Id = n.ProviderId,
Name = n.provider_Name
};
If you do this, the anonymous types shouldn't conflict anymore, since the one you don't modify will use the default names.
Good luck, and I hope this helps!
Convert it into a List or IEnumberable, you just cannot pass anonymous objects as datasource to gridview. query.ToList();
You may convert the return type to
IEnumerable<object>
it can hold any anonymous type and gets easily binded as datasource
I had the same issue and I added another property to the anonymous type and that resolved it.
Linq does not support some functionality like .toDays(),.addDays(),.StartsWith() . So what you need to do is,First get the result without using .StartsWith() then try to apply some functionality to filter result StartsWith perticular id.

Linq To SQL Method with .Contains fails

I have the below Linq To SQL Method. When I step through the code spcCodeIDs contains the seven entries I am expecting. However I get a run-time exception of
Method 'Boolean Contains(System.String)' has no supported translation to SQL.
What am I missing?
public static DataTable GetSPCCodeList()
{
using (var context = ProviderDataContext.Create())
{
IQueryable<tblProviderAdminSPCCode> tSPCCode = context.GetTable<tblProviderAdminSPCCode>();
IList<string> spcCodeIDs = BLLCmo.FCApprovedSPCsForGreenSheet();
return (tSPCCode
.Where(spcCode => spcCode.Inactive == null && spcCodeIDs.Contains(spcCode.SPCCodeID))
.OrderBy(spcCode => spcCode.SPCCodeID)
.Select(spcCode => new { spcCode.SPCCodeID, spcCode.SPCDescription, spcCode.SPCCategoryID }))
.CopyLinqToDataTable();
}
}
LINQ to SQL can only support Contains translations form a concrete list and not the IList interface.. try changing your line from
IList<string> spcCodeIDs = BLLCmo.FCApprovedSPCsForGreenSheet();
to
List<string> spcCodeIDs = BLLCmo.FCApprovedSPCsForGreenSheet().ToList();
You need to pass a string as a parameter to Contains. So trying passing spcCode.SPCCodeID.ToString()

Linq - Is there are way to build up a linq statement from several snippets of linq

I have several methods that use similar linq statements but different enough for them to be in their own methods. So say, for the sake of arguemnt, I had the following linq snippet which is repeated across all methods (the real snippets would be much longer than this):
where su.ObjId == serviceUserId
where cl.StaffMemberId == staffMemberId
If I was working in SQL I could just contatenate the repeated SQL as follows:
private string GetRepeatedSql()
{
return "where su.ObjId = serviceUserId and cl.StaffMemberId = staffMemberId";
}
private void DoSomething()
{
string mySql = "Select * from ...... lots of sql .." + GetRepeatedSql() + ".. some more sql";
}
(Usual health warnings around contatenating SQL string together noted).
Is there something equivalent in Linq? I'm sick of having to make changes in several places - this seems to contravene the DRY principle.
Thanks!
Correct me if I'm wrong but I always thought LINQ statements weren't executed until you actually used them. (Coming from LINQ to NHibernate)
If that is actually the case you could simply just add whatever you need to the existing statement. For example:
var temp=from x in Sometable select x;
Then adding a where clause:
temp = from x in temp where x.ID==1234 select x;
Then order by
temp=from x in temp order by x.ID select x;
I won't lie I have never done it this way but I assume it should work. If someone knows this won't work please explain why. Thanks.
Found this on msdn: http://msdn.microsoft.com/en-us/library/bb397906.aspx
In LINQ the execution of the query is
distinct from the query itself; in
other words you have not retrieved any
data just by creating a query
variable.
So by creating the variable you have not retrieved any data. Although maybe the way I'm doing it above would return data because I am calling from x in temp to change the query.
I do it like this
IQueryable<Publication> pubs = GetPubs();
pubs = ApplySort(pubs, SortBy);
pubs = GetPage(pubs, PageSize, Page);
private IQueryable<Publication> GetPage(IQueryable<Publication> pubs, int PageSize, int Page)
{
return pubs.Skip(PageSize * (Page - 1)).Take(PageSize);
}
private IQueryable<Publication> ApplySort(IQueryable<Publication> pubs, string SortBy)
{
switch (SortBy)
{
case "Latest": return pubs.OrderByDescending(p => p.Posted);
break;
default: return pubs.OrderByDescending(p => p.Posted);
break;
}
}
You can use PredicateBuilder to do this:
The Albahari one here is one I've used recently although there are others around:
http://www.albahari.com/nutshell/predicatebuilder.aspx

Categories

Resources