score:0
If you want a generic method that lets you specify any table and any predicate for records from that table then you can't really get any better than the built-in Where<T>(...)
and (as others have already pointed out) the FirstOrDefault<T>(...)
extension methods.
Your code would then look like so:
var result = _gam.PAC.Where(pac => pac.CODI_PAC == codiPac).FirstOrDefault();
// OR
var result = _gam.PAC.FirstOrDefault(pac => pac.CODI_PAC == codiPac);
The best you could get then, writing your own generic method, would be this:
public T FirstOrDefault<T>(IQueryable<T> source,
Expression<Func<T, bool>> predicate)
{
return source.Where(predicate).FirstOrDefault();
// OR
// return source.FirstOrDefault(predicate);
}
And that is really just redundant. Especially when your calling code would be actually longer using the helper method:
var result = FirstOrDefault(_gam.PAC, pac => pac.CODI_PAC == codiPac);
// versus
var result = _gam.PAC.FirstOrDefault(pac => pac.CODI_PAC == codiPac);
And even worse, your code is no longer using a fluent, composable syntax. This just makes readability and maintenance more difficult.
If you stick with using the IQueryable<T>
extension methods then you can do composition like this:
var result = _gam.PAC
.Where(pac => pac.CODI_PAC == codiPac)
.Where(pac => pac.SomeOtherProperty == someOtherValue)
.FirstOrDefault();
// OR
var result = (from pac in _gam.PAC
where pac.CODI_PAC == codiPac
where pac.SomeOtherProperty == someOtherValue
select pac).FirstOrDefault();
One very important thing to note here is that the predicate
parameter in the IQueryable<T>.Where<T>(...)
extension method is of type Expression<Func<T, bool>>
. This allows the IQueryable<T>
provider to construct the native SQL (or other native provider query) at the very last moment before returning a result.
Not using Expression<Func<T, bool>>
means that your query would be the equivalent of this:
var result =
_gam.PAC
.ToArray()
.Where(pac => pac.CODI_PAC == codiPac)
.FirstOrDefault();
And that would mean the query will load every record from the "PAC" table into memory before selecting the first filtered result and throwing out the rest of the results.
The bottom-line is that by making a generic helper method you are rewriting existing framework code and you open yourself to performance and maintenance issues while also reducing code readability.
I hope this helps.
score:0
I'm not sure if you are asking for this, but this method could be in a static class and method and so you'd be able to call it from everywhere.
score:0
An easy solution will be:
//a generic method
private PAC PAC_GetPAC(Func<PAC, bool> predicate)
{
return _gam.PAC.Where(predicate).FirstOrDefault();
}
public PAC PAC_GetPACById(long id)
{
return PAC_GetPAC(p => p.ID == id);
}
public PAC PAC_GetByCodiPac(string codiPac)
{
return PAC_GetPAC(p => pac.CODI_PAC == codiPac);
}
score:1
I see that what you asked is a very straight forward where
query even doesn't require to have have it on a separate method.
Also you can simply enhance your query link the following:
public PAC PAC_GetByCodiPac(string codiPac)
{
return _gam.PAC.FirstOrDefault(pac => pac.CODI_PAC == codiPac);
}
FirstOrDefault will return the first item on the array, if not it will return null.
score:2
Here is your generic method. Note, that as others pointed out FirstOrDefault is better than count and then first, so I'm using it here. But it's also possible to write the expression so that it mimics what your original code does. Please let me know if you need additional help with this.
public static T GetByCodi<T>(IQueryable<T> table, string codi, string fieldName) where T : class
{
// x
ParameterExpression parameter = Expression.Parameter(typeof(T), "x");
Expression currentExpression = parameter;
Type currentType = typeof(T);
PropertyInfo property = currentType.GetProperty(fieldName);
// x.CODI_xxx
currentExpression = Expression.Property(currentExpression, property);
// x.CODI_xxx == codi
currentExpression = Expression.Equal(currentExpression, Expression.Constant(codi));
// x => x.CODI_xxx == codi
LambdaExpression lambdaExpression = Expression.Lambda(currentExpression, parameter);
return table.FirstOrDefault((Func<T, bool>)lambdaExpression.Compile());
}
You use it like this:
PAC xxx = GetByCodi<PAC>(_gam.PAC, codiPac, "CODI_PAC");
Edit 1: I changed the code according to the comment so that you can pass arbitrary ID field name in.
Source: stackoverflow.com
Related Articles
- Make a Search Method generic using LINQ
- Cast Entity to Implemented Interface in a Generic Method Using LINQ for Entity Framework
- Call Ignore Case for Contains Method using a generic LINQ Expression
- Is it possible to make 1 generic method out of these 2 linq statements?
- How can I make this LINQ search method handle more than two terms?
- Generic Extension method for LINQ JOIN using 2 columns
- How to implement generic method approach using Linq and XML
- Using Linq to build a graph class; can you make this code look better?
- How to implement a generic method in Repository to make joins in linq
- Generic method using Linq and inheritance to bind to object
- ASP.NET Web API: Perform Search on Table using HTTP GET Method and Linq to SQL Dynamically
- LINQ where clause using Generic IQueryable source
- how to make c# method more functional using C# and Linq
- how should I make the following linq generic method returns distinct records?
- Need to build a generic query method using LINQ expressions
- Generic method using linq expressions
- Convert string[] to int[] in one line of code using LINQ
- Code equivalent to the 'let' keyword in chained LINQ extension method calls
- Using LINQ extension method syntax on a MatchCollection
- Ambiguous call when using LINQ extension method on DbSet<T>
- Why does C# compiler create private DisplayClass when using LINQ method Any() and how can I avoid it?
- How to retrieve last 5 records using LINQ method or query expression in C#
- Extension method for IQueryable left outer join using LINQ
- How to Convert LINQ Comprehension Query Syntax to Method Syntax using Lambda
- How do I count the number of child collection's items using LINQ Method Syntax?
- Simplest way to filter value from generic List in C# using LINQ
- AsNoTracking using LINQ Query syntax instead of Method syntax
- Using my own method with LINQ to Entities
- Using Linq to run a method on a collection of objects?
- How do I remove items from generic list, based on multiple conditions and using linq
- Which is more efficient / elegant?
- How to construct List of objects inside linq
- Multiple text box search ASP.NET MVC
- A function to alter a LINQ
- Using Entity Framework to fetch all results within a distance of N
- linq select from array name with value
- How to find numbers in List with condition?
- most matched field value
- Is it possible to prove (programmatically) that two LINQ queries are equal?
- I want to get 2 values returned by my query. How to do, using linq-to-entity
- Linq To Entities - how to filter on child entities
- Grouping Table Data As Column Headers on Excel Sheet
- When using a LINQ Where clause on a Dictionary, how can I return a dictionary of the same type?
- When is OrderBy operator called?
- linq to List problem in C#
- Subsonic3 LINQ Left Outer Join
- Does LINQ know how to optimize "queries"?
- How to group and split items in a list by inline code?
- Loop Through List of Objects until condition is met, then set value of subsequent objects until the condition is met again
- How to parse a list of Dictionarys (List<Dictionary<string, string>>) using linq