How to apply the same query to different objects?

So, I'm starting to use EF, and I'm developing an application that uses it as an ORM. The fact is that I did not have much time to look into the documentation (I plan, in due time), and I got a little lost in some things. For example, I have two queries:

public static int GetNextPadlockNumber() { LockersDBEntities1 entities = new LockersDBEntities1(); var query = (from p in entities.PadLocks select p.PadlockNumber).DefaultIfEmpty(0).Max(); return (int)query + 1; } public static Data.PadLock GetPadLockByNumber(int number) { Data.LockersDBEntities1 entities = new LockersDBEntities1(); var query = (from p in entities.PadLocks where p.PadlockNumber == number select p).FirstOrDefault(); return query; } 

and

 public static int GetNextLockerNumber() { LockersDBEntities1 entities = new LockersDBEntities1(); var query = (from l in entities.Lockers select l.LockerNumber).DefaultIfEmpty(0).Max(); return (int)query+1; } public static Data.Locker GetLockerByNumber(int number) { Data.LockersDBEntities1 entities = new LockersDBEntities1(); var query = (from l in entities.Lockers where l.LockerNumber == number select l).FirstOrDefault(); return query; } 

And the thing is that they are exactly the same. Is there no way to do this without indicating that I want a locker or lock? Thanks in advance to the heroes.

+4
source share
2 answers

One of the great things about EF is that you can do this. This is not trivial, and it will require some trial and error, but you can abstract away many of the complexities of the database.

Now, assuming LockersDBEntities1 is a DbContext , you could have something like this:

 public static class LockersDBEntities1Extensions { public static int GetNextNumber<T>( this LockersDBEntities1 context, Expression<Func<T, int>> getNumberExpression) { var query = (from item in context.Set<T> select getNumberExpression(item)) .DefaultIfEmpty(0) .Max(); return (int)query + 1; } } 

and use it like:

 int nextPadlockNumber = new LockersDBEntities1() .GetNextNumber<Padlock>(p => p.PadlockNumber) 

and

 int nextPadlockNumber = new LockersDBEntities1() .GetNextNumber<Locker>(l => l.LockerNumber) 

The expression getNumberExpression necessary because there is no general way to access a number in all entities. It might be a reevaluation, but if this is a problem, I would do something like this:

 //this should be a better name, to reflect the real scenarion interface ILockNumberProvider { int Number {get; } } 

and implement this interface on Locker , Padlock and other classes that should contain lock numbers. Then, in the above method, the expression can be omitted, and a general constraint can be used, for example:

 public static class LockersDBEntities1Extensions { public static int GetNextNumber<T>(this LockersDBEntities1 context) where T:ILockNumberProvider { var query = (from item in context.Set<T> select item.Number) .DefaultIfEmpty(0) .Max(); return (int)query + 1; } } 
+2
source

You could use the LockerNumber and PadlockNumber fields as Identity auto-increment fields, as that is what you are doing, and then called them the same (like Id).

And in this case, the need to "get the next locker number" is no longer needed, since each added new object will receive the next available number and with the repository template you could use these methods as general methods in the base repository class, like something like this:

 public IEntity GetEntityById(int number) { return ObjectSet.Single(x => x.Id == number); } 
+5
source

All Articles