Task: write a generic extension for Entity Framework entities
I am not sure if this is even possible due to the fact that each entity usually will have differing properties, but I have a group of entities that share a few common properties and all I was wondering if it is even possible to build a generic extension instead of always having to write out the same code for each entity.
I spent a bit of time researching this, but there is not much , which leads me to believe this just is not possible.
Anyway, contrary to my better judgment I am going to ask a stupid question on StackOverFlow.
This is what I was thinking, but obviously a non compile-able example, but at least you will get the idea.
public static List<TEntity> Generic<TEntity>(this DbContext db, string name)
{
return db.TEntity.Where(s => s.Name == name);
}
I poke in the right direction would be appreciated.
And just for clarity, I have never spent a single hour in a classroom for programming, I am self taught, so if it is not possible to this, could the answer explain please explain technically why this is not possible in Entity Framework. As I could not find anything substantial myself.
Thanks to #Bagus Tesa, I was able to solve this.
As Bagus tesa states, make an interface that references the common properties of the Entities and refference the interface with the Entities and make an extension that way.
The code I used,
public static IQueryable<IFilterEntity> FilterEntity(this BaseViewModel vm,
IQueryable<IFilterEntity> list)
{
return list.Where(s => s.Name == vm.name &&
s.DateMonth == vm.Month &&
s.DateYear == vm.Year);
}
The interface,
public interface IFilterEntity
{
string Name { get; set; }
int? DateYear { get; set; }
int? DateMonth { get; set; }
}
The BaseViewModel,
public class BaseViewModel
{
string Name => RootVm.Name;
int? DateYear => RootVm.SelectedDate.Month;
int? DateMonth => RootVm.SelectedDate.Month;
}
Thanks for all the help with. And I hope this helps someone else.
Use this
public IEnumerable<TEntity> Filter(Expression<Func<TEntity, bool>> filter, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null)
{
db.Set<TEntity>().AsNoTracking().AsQueryable().Where(filter);}
Related
I am using Generic Repositories with ASP.NET. Now I am trying to find an object by the user Id which requires to access a property of the class, but ofcourse in the linq expression the property is not know, because it does not know the type yet. Is there any way around this?
public virtual IEnumerable<T> GetByUser(string userId)
{
if (typeof(T).GetProperty("Employee") != null)
{
return Db.Set<T>().Where(x => x.Employee.Id == userId);
}
return new List<T>();
}
the "x.Employee.Id" gets the error that there is no definition of Employee. That is to be expected. Do I need to do this in an entire different way or does somebody knows how to fix this?
I hope anybody can help!
Use interfaces so that you know T will have certain properties. Or use a base type and then use constraints on the generic parameter.
public virtual IEnumerable<T> GetByUser(string userId) where T : IEmployee
{
return Db.Set<T>().Where(x => x.Employee.Id == userId);
}
And where IEmployee looks like this
public interface IEmployee
{
Employee Employee { get; set; }
}
Obviously this is a bit crude, but depending on your entities this could be an approach. You could always map out everything and then build up your interfaces for the shared properties etc.
However to be honest I think your best approach is to have a more functional set of generic repositories. For example a base repo, and then an EmployeeRepostiory that knows that T will be an Employee.
MSDN Article on Constraints
If I'm trying to filter results at multiple levels of an IEnumerable<T> object graph, is there a preferred way of chaining extension methods to do this?
I'm open to any extension method and lambda usage, but I'd prefer not to use LINQ syntax to remain consistent with the rest of the codebase.
Is it better to push the filtering to the selector of the SelectMany() method or just to chain another Where() method? Or is there a better solution?
How would I go about identifying the best option? In this test case, everything is directly available in memory. Obviously both samples below are currently producing the same correct results; I'm just looking for a reason one or the other (or another option) would be preferred.
public class Test
{
// I want the first chapter of a book that's exactly 42 pages, written by
// an author whose name is Adams, from a library in London.
public Chapter TestingIEnumerableTExtensionMethods()
{
List<Library> libraries = GetLibraries();
Chapter chapter = libraries
.Where(lib => lib.City == "London")
.SelectMany(lib => lib.Books)
.Where(b => b.Author == "Adams")
.SelectMany(b => b.Chapters)
.First(c => c.NumberOfPages == 42);
Chapter chapter2 = libraries
.Where(lib => lib.City == "London")
.SelectMany(lib => lib.Books.Where(b => b.Author == "Adams"))
.SelectMany(b => b.Chapters.Where(c => c.NumberOfPages == 42))
.First();
}
And here's the sample object graph:
public class Library
{
public string Name { get; set; }
public string City { get; set; }
public List<Book> Books { get; set; }
}
public class Book
{
public string Name { get; set; }
public string Author { get; set; }
public List<Chapter> Chapters { get; set; }
}
public class Chapter
{
public string Name { get; set; }
public int NumberOfPages { get; set; }
}
Which is best likely varies based on the LINQ implementation you're using. LinqToSql will behave differently from in-memory filtering. The order of the clauses should impact the performance depending on what data is used, since naive implementations will filter more records earlier in the sequence meaning less work for the later methods.
For your two examples, I would guess that the performance difference is negligible and would favor the first since it allows easier modification of each clause independent of the others.
As for determining the best option, it's the same as anything else: measure.
I'm guessing the first expression you have will be slightly but insignificantly faster. To really determine if one or the other is faster, you will need to time them, with a profiler or Stopwatch.
The readability doesn't seem to be strongly affected either way. I prefer the first approach, as it has less levels of nesting. It all depends on your personal preference.
It depends on how the underlying LINQ provider works. For LINQ to Objects, both in this case would require about the same amount of work, more or less. But that's the most straightforward (simplest) example, so beyond that it's hard to say.
This might give you a different angle, though it's more a matter of style...
I sometimes find myself doing something like this...
return libraries.Filter(
l => l.City == "",
l => l.Books,
b => b.Author == "Adams",
b => b.Chapters,
c => c.NumberOfPages == 42
);
...where you can guess what the extensiion is, something like...
public static IEnumerable<TC> Filter<TL, TB, TC>(this IEnumerable<TL> list,
Func<TL, bool> whereLs,
Func<TL, IEnumerable<TB>> selectBs,
Func<TB, bool> whereBs,
Func<TB, IEnumerable<TC>> selectCs,
Func<TC, bool> whereCs
)
{
return list
.Where(whereLs)
.SelectMany(selectBs)
.Where(whereBs)
.SelectMany(selectCs)
.Where(whereCs);
}
...or....
...
{
return list
.Where(whereLs)
.SelectMany(l => selectBs(l).Where(whereBs))
.SelectMany(b => selectCs(b).Where(whereCs));
}
And combinations / options are many, depending on what you have, how you 'like having your code' (abstract it some more or 'capture', 'parametrize' e.g. PerCityAuthorPages(_city, _author, _numPages); etc.)
...basically, I dislike having all the 'Where', 'Select'-s etc. and to me is not that readable (either).
While with the 'short form' it's quite clear which is which, where, select etc. and it's very much 'short-hand' and in much less chars.
Also, you can deffer the decision about Where/Select combinations for later (do one or the other based on the needs, provider)
And #Telastyn is quite right, LINQ providers, e.g. if you look at some implementation code,
with all the expressions reducing etc.
are pretty non-deterministic (i.e. from provider to provider) in a way they might end up mapping to e.g. SQL
though this should map the same in most I think.
I recently got a "The mapping of interface member ..... is not supported" error, which I resolved based on this thread. To demonstrate:
public interface IMyInterface { string valueText { get; set; } }
public class MyData : IMyInterface
{
int ID { get; set;}
string valueText { get; set;}
}
public class MyOtherData : IMyInterface
{
long ID { get; set;}
string valueText { get; set;}
}
and
public static IEnumerable<T> GetByValue<T>(string value) : where T : class, IMyInterface, new()
{
using (var context = new DataContext())
{
// The important line
return context.GetTable<T>().Where(x => x.valueText == value);
}
}
Running this code, I'd get a NotSupportedException: "The mapping of interface member IMyInterface.valueText is not supported". However, if I replace the x.valueText == value with x.valueText.Equals(value), this works entirely as expected.
I've solved this in my code, but I want to understand why it behaves this way. Can anyone explain it?
Update: As per my comment below, the LINQ to SQL team closed this as a "Won't fix". I think that means it now counts as a known bug, but one that isn't going to be resolved any time soon. I'd still like to know why it behaves differently in the first place, though.
Apparently the decision to push the query upstream to the server is made based on an incomplete set of rules, and then LINQ-to-SQL finds a construct (an interface) that it can't deal with.
The method call isn't supported by LINQ-to-SQL, so it generates a query to retrieve all records and then uses LINQ-to-Objects to filter them. (Actually, based on your other thread, LINQ-to-SQL may make a special exception for object.Equals and knows how to convert that to SQL).
LINQ-to-SQL probably should fall back to the LINQ-to-Objects behavior when an interface is involved, but apparently it just throws an exception instead.
Sometimes you need to define some business rules and the Specification pattern is a useful tool. For example:
public class CanBorrowBooksSpec : ISpecification<Customer>
{
public bool Satisfies(Customer customer)
{
return customer.HasLibraryCard
&& !customer.UnpaidFines.Any();
}
}
However, I often find that I need to 'push' these rules into SQL to improve performance or to cater for things like paged lists of records.
I am then left with having to write code for the rules twice, once in CLR code, and once in SQL (or ORM language).
How do you go about organising code like this?
It seems best if the code was kept together in the same class. That way, if the developer is updating the business rules they have less chance of forgetting to update both sets of code. For example:
public class CanBorrowBooksSpec : ISpecification<Customer>
{
public bool Satisfies(Customer customer)
{
return customer.HasLibraryCard
&& !customer.UnpaidFines.Any();
}
public void AddSql(StringBuilder sql)
{
sql.Append(#"customer.HasLibraryCard
AND NOT EXISTS (SELECT Id FROM CustomerUnpaidFines WHERE CustomerId = customer.Id)");
}
}
However this seems quite ugly to me as we are now mixing concerns together.
Another alternative would be using a Linq-To-YourORM solution, as the LINQ code could either be run against a collection, or it could be translated into SQL. But I have found that such solutions are rarely possible in anything but the most trivial scenarios.
What do you do?
We used Specification pattern with Entity Framework. Here's how we approached it
public interface ISpecification<TEntity>
{
Expression<Func<TEntity, bool>> Predicate { get; }
}
public class CanBorrowBooksSpec : ISpecification<Customer>
{
Expression<Func<Customer, bool>> Predicate
{
get{ return customer => customer.HasLibraryCard
&& !customer.UnpaidFines.Any()}
}
}
Then you can use it against LINQ-to-Entities like
db.Customers.Where(canBorrowBooksSpec.Predicate);
In LINQ-to-Objects like
customerCollection.Where(canBorrowBooksSpec.Predicate.Compile());
Here is some code that uses a parameter class to contain the possible parameters to the Show() method. The values in this FooOption class aren't very related. You can see this by looking at the implementation of Show() below. I know this is bad code, but are there any anti-patterns related to doing this?
class FooOptions {
public int? Id { get; set; }
public string BazContext { get; set; }
public int? BazId { get; set; }
}
class BarMgr {
public Bar Show(FooOptions options) {
if (options == null)
options = new FooOptions();
if (options.Id.HasValue)
return svc.GetBar(options.Id.Value);
if (!string.IsNullOrEmpty(options.BazContext) && options.BazId.HasValue)
return svc.GetBar(options.BazContext, options.BazId.Value);
return null;
}
}
Update:
I know that parameter objects are not an anti-pattern. In my experience, parameter object properties are related. This is the possible anti-pattern that I am trying to locate. setting all three properties makes no sense.
After your update, here my answer:
As far as I know, there is no real name for an anti-pattern like this, but there is at least one principle that this method violates:
The Single-Responsibility-Principle.
And it really is a problem of the method and not of the parameter object.
It's called the parameter object pattern, and it's not considered an antipattern -- it's a good way to deal with methods that would otherwise have too many parameters.
There might be an anti-pattern if you use options a lot we have something called feature envy and is an indication that you might want to move functionality into the actual feature being used.