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 Query
- 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
More Query from same tag
- Split comma separated string and compare each value in a List
- performance of LINQ queries against the SQL equivalent
- Rename object, or change it's primary key (_id) value
- Using linq to append list to list from select method
- Dynamic "WHERE" like queries on memory objects
- The long expression could not be translated
- An exception of type 'System.ArgumentException' occurred in EntityFramework.dll but was not handled in user code
- Sorting days of the week based based on current day of the week
- Group by Linq . Count of Key field
- Linq to Entities strange deploying behavior
- Query nested linked lists
- Advanced filtering in linq
- Lambda Syntax for Joins via Navigation Property?
- Query Timeout in EF Core but runs fast in SSMS
- Is there something similar to python's enumerate for linq
- List Group and SubGroup
- What is the return type of my linq query?
- how to sortby a given value a generic type list
- Multiple outer Linq join
- Get an element from IQueryable<anonymous> list by index
- How to pass two LINQ joined tables from Controller to View
- SubString editing
- Can I have a dynamicly updated dataContext?
- List.OrderByDescending Linq not working
- Convert Linq expression "obj => obj.Prop" into "parent => parent.obj.Prop"
- Get results where multiple IDs are present in list (contains all)
- Best way to compare two classes (Users and Holidays) and create a list of Users who have not created an instance of the Holiday class with LINQ
- Regular Expression is missing empty values?
- How to add a data-attribute to a dropdown menu with C#
- Stored procedure with static data not returning values