I have been searching and I have not seen an example like this.
I want to query a Model table to retrieve all Models from German manufacturers.
My data structure is Model Table has a Navigation Property called "Manufacturer" and an FK called "IdManufacturer"
A Manufacturer Has a Navigation Property called "Origin" and an FK called IdOrigin.
I would like to have a query that includes a where clause something like this:
(m => m.Manufacturer.Origin.Name == "German");
I would like this to be dynamically created at run time. Not only the lookup value might change, but the next time even the fields may change to, for example:
(m.Type.Name == "SUV");
Finally, there will not necessarily be a UI associated with this request, it may be generated in code.
Please don't get too hung up on the business of it, I am hoping this made up example will be simple to understand.
Any suggestions on how to handle this would be greatly appreciated. Any general thoughts on performance would be created.
My solution:
I have a model RouteList, in this model I created Expression:
public static Expression<Func<RouteList, bool>> FilterByDateOrShiftCode(RoutesFilterViewModel filter)
{
Expression<Func<RouteList, bool>> result = rl => true;
if (string.IsNullOrEmpty(filter.ShiftCode))
{
result = rl => rl.RouteListDate.Date >= filter.From.Date && rl.RouteListDate.Date <= filter.To.Date && rl.User.Id == filter.User.Id;
}
else
{
result = rl => rl.ShiftCode == filter.ShiftCode && rl.User.Id == filter.User.Id;
}
Place where I use it:
model.RouteLists = await _context.RouteLists
.Include(rl => rl.Status)
.Include(rl => rl.User)
.Include(rl => rl.RouteListRows).ThenInclude(rlr => rlr.Address)
.Where(RouteList.FilterByDateOrShiftCode(filter))
.ToListAsync();
Speed of executing grow in several times.
Try the following simple extension method. Note that this realization will work only with sting properties.
Usage:
query = query.Where("Manufacturer.Origin.Name", "German");
Realization:
public static class QueryableExtensions
{
public static IQueryable<T> Where<T>(this IQueryable<T> query, string propPath, string value)
{
var param = Expression.Parameter(typeof(T), "e");
// e.Prop1.Prop2 == value
var body = Expression.Equal(MakePropPath(param, propPath), Expression.Constant(value));
// e => e.Prop1.Prop2 == value
var predicateLambda = Expression.Lambda<Func<T, bool>>(body, param);
return query.Where(predicateLambda);
}
static Expression MakePropPath(Expression objExpression, string path)
{
return path.Split('.').Aggregate(objExpression, Expression.PropertyOrField);
}
}
Related
In short, I'm looking to do what this guy did, but with Entity Framework 6.
Implementing the proposed solution results in the error "The LINQ expression node type 'Invoke' is not supported in LINQ to Entities." Since the proposed solution uses Invoke, this is obviously an issue.
I understand that there's a way to harness a custom Compose method to rewrite the expression tree without using Invoke, but I can't seem to wrap my head around it.
Here's what I'm trying to write.
I build an IQueryable<TEntity> dynamically using a QueryParameters object that's just a bag of properties to use for the WHERE clauses. TEntity is a standard code-first EF entity with data annotations all over the place. The query contruction looks something like this:
IQueryable<TEntity> query = Context.Set<TEntity>();
if (queryParams == null)
return query;
if (!string.IsNullOrWhiteSpace(queryParams.FirstName))
{
if (queryParams.ExactSearch)
{
query = query.Where(x => x.FirstName == queryParams.FirstName);
}
else
{
if (queryParams.PreferStartsWith)
{
query = query.Where(
x => x.FirstName.ToLower()
.StartsWith(
queryParams.FirstName
.ToLower()));
}
else
{
query = query.Where(
x => x.FirstName.ToLower()
.Contains(
queryParams.FirstName
.ToLower()));
}
}
}
// ... repeat for all of queryParams' string props.
// DateTime, int, bool, etc have their own filters.
This gets repeated for every query parameter for a string field to be queried. Obviously, this results in a lot of repeated code. I would love to be able to write a filter with a signature like this:
public static IQueryable<TEntity> Search<TEntity>(
this IQueryable<TEntity> query,
Expression<Func<TEntity, string>> fieldExpression,
string searchValue,
bool exactSearch = true,
bool useStartsWithOverContains = false) {...}
Which I can then consume like this:
if (!string.IsNullOrWhiteSpace(queryParams.FirstName))
{
query = query.Search(
x => x.FirstName,
queryParams.FirstName,
queryParams.ExactSearch,
queryParams.PreferStartsWith);
}
The closest I've come a definition for that extension method is the below, but as mentioned, it produces that "'Invoke' is not supported in LINQ to Entities" error:
public static IQueryable<TEntity> Search<TEntity>(
this IQueryable<TEntity> query,
Expression<Func<TEntity, string>> fieldExpression,
string searchValue,
bool exactSearch = true,
bool useStartsWithOverContains = false)
{
if (string.IsNullOrWhiteSpace(searchValue))
return query;
searchValue = searchValue.Trim();
Expression<Func<TEntity, bool>> expression;
if (exactSearch)
{
var x = Expression.Parameter(typeof(TEntity), "x");
var left = Expression.Invoke(fieldExpression, x);
var right = Expression.Constant(searchValue);
var equalityExpression = Expression.Equal(left, right);
expression = Expression.Lambda<Func<TEntity, bool>>(
equalityExpression,
x);
}
else
{
searchValue = searchValue.ToLower();
var x = Expression.Parameter(typeof(TEntity), "x");
var fieldToLower = Expression.Call(
Expression.Invoke(fieldExpression, x),
typeof(string).GetMethod(
"ToLower",
Type.EmptyTypes));
var searchValueExpression =
Expression.Constant(searchValue);
var body = Expression.Call(
fieldToLower,
typeof(string).GetMethod(
useStartsWithOverContains ? "StartsWith" : "Contains",
new[] { typeof(string) }),
searchValueExpression);
expression = Expression.Lambda<Func<TEntity, bool>>(
body,
x);
}
return query.Where(expression);
}
I started to include the Compose method I mentioned, but I got lost really quickly, and thus removed it.
Open to any guidance! Thank you!
This is much easier to do by composing expressions than it is by trying to manually construct the expressions every single time. It's faster to write, so much less error prone, and actually ends up with code you can actually read at the end of it. All you need to do is write the code for how you use the value in the composed expression, which you already have from your original code.
public static IQueryable<TEntity> Search<TEntity>(
this IQueryable<TEntity> query,
Expression<Func<TEntity, string>> fieldExpression,
string searchValue,
bool exactSearch = true,
bool useStartsWithOverContains = false)
{
if (string.IsNullOrWhiteSpace(searchValue))
return query;
searchValue = searchValue.Trim();
if (exactSearch)
{
return query.Where(fieldExpression.Compose(field => field == searchValue));
}
else if (useStartsWithOverContains)
{
return query.Where(fieldExpression.Compose(field => field.StartsWith(searchValue.ToLower())));
}
else
{
return query.Where(fieldExpression.Compose(field => field.Contains(searchValue.ToLower())));
}
}
Note you should probably go with an enum for "Comparison" or something like that, rather than having two booleans. For example, right now someone can say that they don't want an exact sure but that they do want to use starts with. Just have one parameter with the three options.
I have an existing function like this
public int sFunc(string sCol , int iId)
{
string sSqlQuery = " select " + sCol + " from TableName where ID = " + iId ;
// Executes query and returns value in column sCol
}
The table has four columns to store integer values and I am reading them separately using above function.
Now I am converting it to Entity Framework .
public int sFunc(string sCol , int iId)
{
return Convert.ToInt32(TableRepository.Entities.Where(x => x.ID == iId).Select(x => sCol ).FirstOrDefault());
}
but the above function returns an error
input string not in correct format
because it returns the column name itself.
I don't know how to solve this as I am very new to EF.
Any help would be appreciated
Thank you
Not going to be useful for the OP 8 years later, but this question has plenty of views, so I thought it could be helpful for others to have a proper answer.
If you use Entity Framework, you should do Linq projection (Select()), because that leads to the correct, efficient query on the db side, instead of pulling in the entire entity.
With Linq Select() you normally have to provide a lambda, though, so having your your column/property name in a string poses the main difficulty here.
The easiest solution is to use Dynamic LINQ (EntityFramework.DynamicLinq Nuget package). This package provides alternatives to the original Linq methods, which take strings as parameters, and it translates those strings into the appropriate expressions.
Example:
async Task<int> GetIntColumn(int entityId, string intColumnName)
{
return await TableRepository.Entities
.Where(x => x.Id == entityId)
.Select(intColumnName) // Dynamic Linq projection
.Cast<int>()
.SingleAsync();
}
I also made this into an async call, because these days all database calls should be executed asynchronously. When you call this method, you have to await it to get the result (i.e.: var res = await GetIntColumn(...);).
Generic variation
Probably it's more useful to change it into an extension method on IQueryable, and make the column/property type into a generic type parameter, so you could use it with any column/property:
(Provided you have a common interface for all your entities that specifies an Id property.)
public static async Task<TColumn> GetColumn<TEntity, TColumn>(this IQueryable<TEntity> queryable, int entityId, string columnName)
where TEntity : IEntity
{
return await queryable
.Where(x => x.Id == entityId)
.Select(columnName) // Dynamic Linq projection
.Cast<TColumn>()
.SingleAsync();
}
This is called like this: var result = await TableRepository.Entities.GetColumn<Entity, int>(id, columnName);
Generic variation that accepts a list of columns
You can extend it further to support selecting multiple columns dynamically:
public static async Task<dynamic> GetColumns<TEntity>(this IQueryable<TEntity> queryable, int entityId, params string[] columnNames)
where TEntity : IEntity
{
return await queryable
.Where(x => x.Id == entityId)
.Select($"new({string.Join(", ", columnNames)})")
.Cast<dynamic>()
.SingleAsync();
}
This is called like this: var result = await TableRepository.Entities.GetColumns(id, columnName1, columnName2, ...);.
Since the return type and its members are not known compile-time, we have to return dynamic here. Which makes it difficult to work with the result, but if all you want is to serialize it and send it back to the client, it's fine for that purpose.
This might help to solve your problem:
public int sFunc(string sCol, int iId)
{
var _tableRepository = TableRepository.Entities.Where(x => x.ID == iId).Select(e => e).FirstOrDefault();
if (_tableRepository == null) return 0;
var _value = _tableRepository.GetType().GetProperties().Where(a => a.Name == sCol).Select(p => p.GetValue(_tableRepository, null)).FirstOrDefault();
return _value != null ? Convert.ToInt32(_value.ToString()) : 0;
}
This method now work for dynamically input method parameter sCol.
Update:
This is not in context of current question but in general how we can select dynamic column using expression:
var parameter = Expression.Parameter(typeof(EntityTable));
var property = Expression.Property(parameter, "ColumnName");
//Replace string with type of ColumnName and entity table name.
var selector = Expression.Lambda<Func<EntityTable, string>>(property, parameter);
//Before using queryable you can include where clause with it. ToList can be avoided if need to build further query.
var result = queryable.Select(selector).ToList();
You have to try with dynamic LINQ. Details are HERE
Instead of passing the string column name as a parameter, try passing in a lambda expression, like:
sFunc(x => x.FirstColumnName, rowId);
sFunc(x => x.SecondColumnName, rowId);
...
This will in the end give you intellisense for column names, so you avoid possible errors when column name is mistyped.
More about this here: C# Pass Lambda Expression as Method Parameter
However, if you must keep the same method signature, i.e. to support other/legacy code, then you can try this:
public string sFunc(string sCol , int iId)
{
return TableRepository.Entities.Where(x => x.ID == iId).Select(x => (string) x.GetType().GetProperty(sCol).GetValue(x)});
}
You might need to adjust this a bit, I didn't have a quick way of testing this.
You can do this:
var entity = _dbContext.Find(YourEntity, entityKey);
// Finds column to select or update
PropertyInfo propertyInfo = entity.GetType().GetProperty("TheColumnVariable");
I'm building a filtering system for UserProfiles based on known properties but unknown (until runtime) combination of filtering conditions.
In my previous question How do I create a generic Expression that has an expression as a parameter, I've figured out a way to have a FilterDefinition for any value property reachable from User entity via navigation properties (i.e. (User)u=> u.NavigationProperty.AnotherNavigationProperty.SomeValue)
and I have a method that can return a predicate as Expression<Func<User,bool>> for a given property, operation ( > < == etc ) and a value.
Now the time has come to filter them on collection properties as well.
Say for example User has CheckedOutBooks collection (which is a total fiction, but will do)
And I need to create a filter definition for Name property of CheckedOutBooks collection on User object.
What I have:
A collection of Users
User class has a collection of Books
now I would like to create a method
Expression<Func<User,bool>> GetPredicate(Expression<User,TProperty>, Operations operation, TProperty value)
That I can call like GetPredicate(u=>u.Books.Select(b=>b.Name), Operations.Contains, "C# in a nutshell")
and get an expression back similar to
u=>u.Books.Any(b=>b.Name == "C# in a nutshell")
I'm thinking maybe it will be easier to split first parameter in two to achieve this.
Maybe u=>u.Books and b=>b.Name will do better?
EDIT:
what I got so far:
class FilterDefinitionForCollectionPropertyValues<T>:FilterDefinition, IUserFilter
{
public Expression<Func<UserProfile, IEnumerable<T>>> CollectionSelector { get; set; }
public Expression<Func<T, string>> CollectionPropertySelector { get; set; }
public Expression<Func<Profile.UserProfile, bool>> GetFilterPredicateFor(FilterOperations operation, string value)
{
var propertyParameter = CollectionPropertySelector.Parameters[0];
var collectionParameter = CollectionSelector.Parameters[0];
// building predicate to supply to Enumerable.Any() method
var left = CollectionPropertySelector.Body;
var right = Expression.Constant(value);
var innerLambda = Expression.Equal(left, right);
Expression<Func<T, bool>> innerFunction = Expression.Lambda<Func<T, bool>>(innerLambda, propertyParameter);
var method = typeof(Enumerable).GetMethods().Where(m => m.Name == "Any" && m.GetParameters().Length == 2).Single().MakeGenericMethod(typeof(T));
var outerLambda = Expression.Call(method, Expression.Property(collectionParameter, typeof(UserProfile).GetProperty("StaticSegments")), innerFunction);
throw new NotImplementedException();
}
}
Now this one works awesomely and does exactly what's needed, now the only thing I need to figure out is how to replace typeof(UserProfile).GetProperty("StaticSegments")) somehow to use CollectionPropertySelector that is in current example would be (UserProfile)u=>u.StaticSegments
You're almost done. Now you just need to do a little trick - wrap your CollectionPropertySelector lambda expression in the CollectionSelector lambda expression.
Expression<Func<TParent,bool>> Wrap<TParent,TElement>(Expression<Func<TParent, IEnumerable<TElement>>> collection, Expression<Func<TElement, bool>> isOne, Expression<Func<IEnumerable<TElement>, Func<TElement, bool>, bool>> isAny)
{
var parent = Expression.Parameter(typeof(TParent), "parent");
return
(Expression<Func<TParent, bool>>)Expression.Lambda
(
Expression.Invoke
(
isAny,
Expression.Invoke
(
collection,
parent
),
isOne
),
parent
);
}
You may have to change this a bit to be used for your particular scenario, but the idea should be clear. My test looked basically like this:
var user = new User { Books = new List<string> { "Book 1", "Book 2" }};
var query = Wrap<User, string>(u => u.Books, b => b.Contains("Bookx"), (collection, condition) => collection.Any(condition));
So you specify the collection selector, predicate and predicate operator, and you're done.
I've written it as a generic method for clarity, but it's dynamic, not strongly typed in essence, so it should be pretty easy to change it to non-generic, if you need that.
Ok I've got it solved for myself.
And I published it to gitHub:
https://github.com/Alexander-Taran/Lambda-Magic-Filters
Given the filter definition class (not reafactored to support properties other than string so far, but will do later):
class FilterDefinitionForCollectionPropertyValues<T>:FilterDefinition, IUserFilter
{
//This guy just points to a collection property
public Expression<Func<UserProfile, IEnumerable<T>>> CollectionSelector { get; set; }
// This one points to a property of a member of that collection.
public Expression<Func<T, string>> CollectionPropertySelector { get; set; }
//This one does the heavy work of building a predicate based on a collection,
//it's member property, operation type and a valaue
public System.Linq.Expressions.Expression<Func<Profile.UserProfile, bool>> GetFilterPredicateFor(FilterOperations operation, string value)
{
var getExpressionBody = CollectionPropertySelector.Body as MemberExpression;
if (getExpressionBody == null)
{
throw new Exception("getExpressionBody is not MemberExpression: " + CollectionPropertySelector.Body);
}
var propertyParameter = CollectionPropertySelector.Parameters[0];
var collectionParameter = CollectionSelector.Parameters[0];
var left = CollectionPropertySelector.Body;
var right = Expression.Constant(value);
// this is so far hardcoded, but might be changed later based on operation type
// as well as a "method" below
var innerLambda = Expression.Equal(left, right);
Expression<Func<T, bool>> innerFunction = Expression.Lambda<Func<T, bool>>(innerLambda, propertyParameter);
// this is hadrcoded again, but maybe changed later when other type of operation will be needed
var method = typeof(Enumerable).GetMethods().Where(m => m.Name == "Any" && m.GetParameters().Length == 2).Single().MakeGenericMethod(typeof(T));
var outerLambda = Expression.Call(method, Expression.Property(collectionParameter, (CollectionSelector.Body as MemberExpression).Member as System.Reflection.PropertyInfo), innerFunction);
var result = Expression.Lambda<Func<UserProfile, bool>>(outerLambda, collectionParameter);
return result;
}
}
Hi I Create a winform Application in c#.
I use EF5 to work with database.
and for bind data to my datagridviews i created a component from BindingSource that has a Bind() method that run this event:
private object bindingSourceTbl1_DataSourceBinding(object sender, EventArgs e)
{
using (SampleDbEntities dbo = new SampleDbEntities())
{
return(from x in dbo.Tbl1
where x.Id == (int)comboBoxPerson.SelectedValue
select x).Take(1000).ToList();
}
}
because my database has many large data i fetch partial of data.
and i use search for get match record. for this i created a SearchPanel component that create textboxes for filter each columns in my grid.
at now i want to send an expression tree to my event as a parameter to join to where clause like this:
private object bindingSourceTbl1_DataSourceBinding(object sender, EventArgs e,Expression whereClause)
{
using (SampleDbEntities dbo = new SampleDbEntities())
{
return(from x in dbo.Tbl1
where x.Id == (int)comboBoxPerson.SelectedValue && whereClause
select x).Take(1000).ToList();
}
}
but my expression tree builder method exists in my component code and i dont access to my DbContext in my project and just i have fieldNames in my component, also i want to write just one method for all tables.
this means i can't return like
Expression< Func< AnyDbSet,bool>>
and i don't know how do it?
Thanks
If you need just &&, then it's helpful to realize that coll.Where(x => a(x) && b(x)) (where a(x) and b(x) are any boolean expressions that work with x) is logically the same as coll.Where(x => a(x)).Where(x => b(x)). What this means is that you can rewrite your code to something like:
List<Tbl1Type> GetTbl1Values(Expression<Func<Tbl1Type, bool>> whereClause)
{
using (SampleDbEntities dbo = new SampleDbEntities())
{
return dbo.Tbl1
.Where(x => x.Id == (int)comboBoxPerson.SelectedValue)
.Where(whereClause)
.Take(1000).ToList();
}
}
If you also needed to support || or more complicated combinations, you could use LINQKit.
This just leaves the matter of creating the expression from a property name. You can use method of the Expression type for that. For example, something like:
static Expression<Func<T, bool>> CreateWhereClause<T>(
string propertyName, object propertyValue)
{
var parameter = Expression.Parameter(typeof(T));
return Expression.Lambda<Func<T, bool>>(
Expression.Equal(
Expression.Property(parameter, propertyName),
Expression.Constant(propertyValue)),
parameter);
}
I would recommend using the PredicateBuilder by Joseph Albahari. You can find it at http://www.albahari.com/nutshell/predicatebuilder.aspx.
your can use dynamic linq.
here is a example:
var result = northwind.Products
.Where("CategoryID = 3 AND UnitPrice > 3")
.OrderBy("SupplierID");
===
private object bindingSourceTbl1_DataSourceBinding(object sender, EventArgs e,Expression whereClause)
{
using (SampleDbEntities dbo = new SampleDbEntities())
{
var q = from x in dbo.Tbl1
where x.Id == (int)comboBoxPerson.SelectedValue && whereClause
select x);
q = q.Where(whereClause)// your must reference dynamic linq library.
//whereClause is expression
.Take(100);
return q.ToList();
}
}
I have a method in my project that repeats over and over:
public PAC PAC_GetByCodiPac(string codiPac)
{
var sel = _gam.PAC.Where(pac => pac.CODI_PAC == codiPac);
if (sel.Count() > 0)
return sel.First();
return null;
}
The table PAC means (patient), so I have these methods for all the tables I have.
How can I make a generic method for this?
Thanks in advance.
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.
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.
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.
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.
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);
}