We are working on improving our DAL which is written in LINQ that talks to the MS SQL database. Our goal is to achieve good re-usability with as little code as possible.
LINQ generated files are making a use of generics and reflection to map LINQ generated classes to the SQL objects (tables and views in our case).
Please see the example of the existing accessor. This method resides in the partial class that contains custom constructors, accessors and mutators:
public clsDVD getDVD(int dvdId)
{
try
{
using (DataContext dvdDC = new DataContext(ConnectionStringManager.getLiveConnStr()))
{
// Deferred loading
dvdDC.DeferredLoadingEnabled = false;
var tDVD = dvdDC.GetTable<DVD>();
return (from t in tDVD
// Filter on DVD Id
where t.DVDId == (dvdId)
select t).Single();
}
catch (Exception e)
{
Logger.Log("Can't get requested DVD.", e);
throw;
}
}
I believe that this is very easy to maintain, since the most of the work is done after var tDVD
It has been suggested not to declare tDVD at all and use dataContext.TableName, but behind the scenes it still calls GetTable<>.
The only way I can see of improving this is breaking this one partial class into 4 (CRUD) partial classes. E.g.
clsDVD_Select, clsDVD_Update, clsDVD_Insert, clsDVD_Delete
In this case each class will represent a set of behaviours.
The idea that we are discussing is to see whether it's possible to use generics on top of LINQ generics.
For example, instead of having the partial classes, we would figure out the properties of the class on the go by using reflection against the SQL database. My first concern here is performance impact. How significant will it be.
Instead of ClsDVD.getDVD(1231) we'd have something on the lines of: GenericDC.Select<DVD>(1231)
.Select method would figure out the primary key and run a select query on that table. I'm struggling to understand how can this work. Lets say we can get this to work for the simple select, i.e. select with a filter on primary key, but what is going to happen when we start doing complex joins and group by selects. What happens when we want to have multiple selects per DVD class?
My final concern is to do with good practices. I have been told before that it's good to have consistant code. For example, If I decide to use datatables , than I should stick to datatables throughout the project. It's a bad idea to have half of the project with datatables and another half with user defined classes. Do you agree on this?
I'm in a position where I think that existing implementation is quite good but maybe I'm missing out something very obvious and there is a much easier, more OO way of achieving the same results?
Thank you
Here is one way to make this situation a little more generic. Rince and repeat for the other CRUD opperations. For some sitiations the performance may be unacceptable. In those cases I would restructure that part of the program to call a non generic version.
public T GetSingleItem(Func<T,bool> idSelector ) where T : ??? // forgot what type it needs to be off the top of my head
{
try
{
using (DataContext context = new DataContext(ConnectionStringManager.getLiveConnStr()))
{
context.DeferredLoadingEnabled = false;
return context.GetTable<T>().Single( item => idSelector( item );
}
}
catch (Exception e)
{
Logger.Log("Can't get requested item.", e);
throw;
}
}
This would be how you woudl have to get the item. Not quite as elegant becase you have to tell the generic function which column you are going to be using.
GenericDC.GetSingleItem<DVD>( dvd => dvd.ID == 1231 )
To make this even more generic that limiting it to a single item with an ID...
public IEnumerable<T> GetItems(Func<T,bool> selectFunction ) where T : ??? // forgot what type it needs to be off the top of my head
{
try
{
using (DataContext context = new DataContext(ConnectionStringManager.getLiveConnStr()))
{
context.DeferredLoadingEnabled = false;
return context.GetTable<T>().Select( item => selectFunction( item );
}
}
catch (Exception e)
{
Logger.Log("Can't get requested item.", e);
throw;
}
}
Then you can call it like:
GenericDC.GetItems<DVD>( dvd => dvd.Title == "Title" && dvd.Cast.Contains( "Actor" ) );
Another possible solution would be to create a custom code generator that could you could modify in one place and create the similar routines for all other types. This would probably be a good solution if you are running into performace problems. You would want to limit the changes to the template piece of code that you use.
Related
Sometime ago I removed a chain of responsibility in a web site that I'am working on.
The chain would call a method to generate a dynamic form for the website. Every object called would either return their form or "pass the ball" to the next object to retrieve the form.
The website has around 300+ classes with this logic, no big deal in terms of performance but I found it horrible to see it and debugging it.
So I decided to remove the chain call and just replaced it with reflection, I know what object I have to call by a unique static "name" (the same name was used in the chain to check if the object has to load the form or "pass the ball") of the class and by foreaching all the objects in a list I'll check that name to be sure to call the correct class/method.
I know that reflection is supposed to be slower in terms of performance but after some tests I can't see any sustantial difference and since the code is much cleaner it's easier to understand and debug.
So my question is:
Is this a correct approach or is there any better pattern to use in a case like this ?
I feel like I use reflection more then I should when I'am coding and I don't know if it is always the better option.
This in 1 class:
foreach (TemplateHandler t in objectList)
{
if (t.GetType().GetProperty("serviceCode") != null)
{
if (t.GetType().GetProperty("serviceCode").GetValue(t).ToString() == serviceCodeToCallFromParam)
{
return t.GetTemplateParam(serviceCodeToCallFromParam/*, ...other params...*/);
}
}
}
over this in 300+ class:
public override List<Form> GetTemplateParam(string serviceCode)
{
if (serviceCode == ClassServiceCode)
{
// long form logic build.
//..
}
else
{
if (successor != null)
form = successor.GetTemplateParam(serviceCode);
}
return form;
}
Reflection solution looks better if I have to choose from those two. Passing ball for 300 times looks meaningless.
But, as you noted, the performance might be the issue. If you already know the class to call for getting work done, why not implement something like Builder or Factory pattern to create an instance of appropriate class and get the work done through.
Even simpler is the switch-case structure. Put and creation code in switch-case and use the resultant object to do work.
Edit 1:
public T CreateTemplate<T>() where T : ITemplate
{
ITemplate template = null;
if(typeof(T) == typeof(Type1Template))
template = new Type1Template(....);
else if(typeof(T) == typeof(Type2Template))
template = new Type2Template(....);
else
throw new TemplateException("Template type is not configured.");
return (T)template;
}
Edit 2
See if something like below helps then:
public T CreateTemplate<T>()
{
ITemplate template = (T)Activator.CreateInstance(typeof(T));
return template;
}
I have done so to avoid extra View Model mappings in Business class.
Example:
public class PatientInfoBusiness
{
public List<PatientInfo> GetPatientInfo()
{
IPatientInfoService proxy = new VRFactory().GetPatientInfoServiceProxy();
var piData= proxy.GetPatientInfoSectionData();
//var patientInfoVM= new List<patientInfoVM>();
//piData.ForEach( a => patientInfoVM.Add(
// new patientInfoVM
// {
// AcknowledgedUserName = a.AcknowledgedUserName,
// Description = a.Description,
// PriorityCode = a.PriorityCode,
// Status = a.Status
// }
// )
// );
return piData;
}
}
Shifted the commented code in the above Business to View, looping through and displaying in HTML. This way no need of patientInfoVM View Model. But I am skipping the business layer altogether and binding the entity from service layer directly in view!
I don't think the Maintainability vs Performance shouldn't be the question here. It's all about time. The less time you need to develop/read/modify your solution, the better. Therefore you need to split your solution in layers. If something changes in the data-layer, you shouldn't have to modify your gui-layer.
Pre-optimalizations should not be done. But there are a few tricks to write your code more efficient.
You might return an IEnumerable<patientInfoVM>. This will create the patientInfoVM lazy. This will only create the item when iterated.
public class PatientInfoBusiness
{
public IEnumerable<PatientInfo> GetPatientInfo()
{
IPatientInfoService proxy = new VRFactory().GetPatientInfoServiceProxy();
var piData= proxy.GetPatientInfoSectionData();
return piData.Select(a => new patientInfoVM
{
AcknowledgedUserName = a.AcknowledgedUserName,
Description = a.Description,
PriorityCode = a.PriorityCode,
Status = a.Status
});
}
}
If you iterate the result only ones, you can just use it like this:
foreach(var patientInfo in GetPatientInfo())
{
// do something.
}
But if you need to use the results more than ones, you should persist the items:
var patientInfoList = GetPatientInfo().ToArray();
foreach(var patientInfo in patientInfoList)
{
// do something.
}
foreach(var patientInfo in patientInfoList)
{
// do something.
}
Without any hard metrics I can only offer my opinion, but in lieu of other, more analytics-driven responses, here it is.
I would say yes, putting your business logic in a separate layer will cause slightly more overhead and therefore worse performance. Then again I would also say that I could squeeze more performance if I wrote in raw machine code, but that would be crazy. So here are my reasons why the slightly worse performance is worth it:
maintenance of data-access code mixed in throughout your views will become a nightmare - you will end up re-writing the same access boilerplate code many times over (as you can't reuse the query logic in other views)
views are typically JIT-compiled (unless you switch that off), and often the intellisense doesn't fully catch up with what you are doing, so you can leak compile-time bugs through to runtime
debugging through views sucks - it just does
mixing of your presentation code and your business logic is generally a "bad idea" - mainly because the two concerns become far too intermingled
you are using a List<> in your example, which is a lower-performance convenience structure: so it's OK for that, why not for MVC?
how do you error-handle in your view? Are you catching exceptions and outputting different markup? How does that translate into display templates, partial views and other such things?
Anyway, that's all my opinion: just ask yourself why you are using this framework, and what that last drop of performance might cost you in other ways. But the decision is up to you.
Enclosed below is an example of one of the methods that I created.
Am I correctly implementing EF6? As you can see in my commented code I first tried to create a repository class. I instead scrapped the repository class for this implementation. However I am now getting errors because I am returning an IQueryable object and then closing the dbcontext.
So this led me to the question: Am I implementing EF6 correctly?
I could change the IQueryable to return a List<obj> or I could remove the using (_myContext) statement. I'm just trying to understand the correct way to implement my methods.
public IQueryable<MY_USERS> GetAllUsers()
{
using (_myContext)
{
return _myContext.MY_USERS;
}
//MyRepository<MY_USERS> users = new MyRepository<MY_USERS>(_myContext);
//return users.GetAll();
}
Updated example:
public void DeleteUser(string userName)
{
using (var context = new MyEFConn())
{
using (var transaction = context.Database.BeginTransaction())
{
try
{
context.MY_USER_GROUPS.RemoveRange(GetUserGroups(userName));
context.MY_USERS.Remove(new MY_USERS { USER_NAME = userName });
transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
throw ex;
}
}
}
}
There is no no wrong or right, it just depends.
When you use IQueriable this mean that you can have common queries in your repository class and outside of it you can append additional filter.
GetAllUsers().Where(u=>u.UserType== 'Test').ToList()
You can also use include depends on your needs let say in MVC controller
GetAllUsers().Include(u=>u.Roles).Take(10).ToList();
Important thing to note, EF dont connect to db until you do ToList() or iterate throw query.
Lastly as you mentioned in comment always need to remember when you use IQuerieable that context could be disposed so this should be taken to consideration too.
On the other side could be good option return IEnumerable from repositories, so lets say if you want to load users you should have method which will require input parameters for paging, filtering or other stuff. This is useful for testing because you will be able to mock data.
About Delete it always depends on your requirements and if you need to remove all together or nothing than you need to use transactions IN addition it could be same about all CRUD.
The project I am currently working on used Linq to SQL as an ORM data access technology. Its an MVC3 Web app. The problem I faced was primarily due to the inability to mock (for testing) the DataContext which gets autogenerated by the DBML designer.
So to solve this issue (after much reading) I refactored the repository system which was in place - single repository with seperate and duplicated access methods for each table which ended up with something like 300 methods only 10 of which were unique - into a single repository with generic methods taking the table and returning more generic types to the upper reaches of the application. The DataContext is now wrapped, and easily mocked.
[Edit: To achieve this i have used the link provided by Jacob below, coincidently!]
My question revolves more around the design I've used to get thus far and the differences I'm noticing in the structure of the app.
1) Having refactored the code which used classic Linq to SQL queries:
public Billing GetBilling(int id)
{
var result = (
from bil in _bicDc.Billings
where bil.BillingId == id
select bil).SingleOrDefault();
return (result);
}
it now looks like:
public T GetRecordWhere<T>(Expression<Func<T, bool>> predicate) where T : class
{
T result;
try
{
result = _dataContext.GetTable<T>().Where(predicate).SingleOrDefault();
}
catch (Exception ex)
{
throw ex;
}
return result;
}
and is used by the controller with a query along the lines of:
_repository.GetRecordWhere<Billing>(x => x.BillingId == 1);
which is fine, and precisely what I wanted to achieve.
...however.... I'm also having to do the following to get precisely the result set i require in the controller class (the highest point of the app in essence)...
viewModel.RecentRequests = _model.GetAllRecordsWhere<Billing>(x => x.BillingId == 1)
.Where(x => x.BillingId == Convert.ToInt32(BillingType.Submitted))
.OrderByDescending(x => x.DateCreated).
Take(5).ToList();
This - as far as my understanding is correct - is now using Linq to Objects rather than the Linq to SQL queries I was previously? Is this okay practise? It feels wrong to me but I dont know why. Probably because the logic of the queries is in the very highest tier of the app, rather than the lowest, but... I defer to you good people for advice. One of the issues I considered was bringing the entire table into memory but I understand that using the Iqeryable return type the where clause is taken to the database and evaluated there. Thus returning only the resultset i require... i may be wrong.
And if you've made it this far, well done. Thank you, and if you have any advice it is very much appreciated!!
Update: Inclusion of GetAllRecordsWhere method as requested
public IQueryable<T> GetAllRecordsWhere<T>(Expression<Func<T, bool>> predicate) where T : class
{
return _dataContext.GetTable<T>().Where(predicate);
}
which uses:
public IQueryable<TName> GetTable<TName>() where TName : class
{
return _db.GetTable<TName>().AsQueryable();
}
If _model.GetAllRecordsWhere returns an IQueryable then your subsequent querying is still just building up an expression tree (which is what i think you mean by using LinqToSql), it only gets turned into SQL an executed when you enumerate the collection by iterating over it or calling ToList() or ToArray().
As an aside don't do this:
catch (Exception ex)
{
throw ex;
}
All you are doing is swallowing the stack trace. If you want to rethrow an exception just call throw, never throw ex. If you don't do anything in your catch other than rethrow then don't catch. The nowmal pattern for this would be catch, do some logging, rethrow.
If you want to mock database context see this:
http://andrewtokeley.net/archive/2008/07/06/mocking-linq-to-sql-datacontext.aspx
Here is a good article that explains how to mock out your DataContext:
Faking your LINQ provider part 1
I had asked this question previously on SO. This is related to it. We have code base similar to this:
IRecipie FindRecipiesYouCanMake(IEnumerable<Ingredientes> stuff, Cook cook)
{
if(stuff.Any(s=>s.Eggs && s.Flour) && cook.DinerCook)
{
if(s=>s.Sugar)
return new Pancake("Yum");
if(s=>s.Salt)
return new Omlette("Yay");
}
/*.....
......
.....
loads of ifs and buts and else*/
}
I want to get rid of this mess and take a more data structure and OO route. Even the code sample i have provided is not as horrendous as it is. I looked at the specification pattern and found it applicable. Any ideas how to improve the code.
EDIT: Now that I realize it, I might even like to implement a method of this signature:
List<IRecipe> WhatAllCanBeCooked(IEnumerable<Ingredients> stuff, Cook cook);
I would delegate this logic to the individual IRecipie classes:
if (Pancake.CanBeMadeBy(stuff, cook)) {
return new Pancake("Yum");
}
....
public class Pancake: IRecipe {
...
public static bool CanBeMadeBy(IEnumerable<Ingredientes> stuff, Cook cook) {
return stuff.Any(s=>s.Eggs && s.Flour && s.Sugar) && cook.DinerCook;
}
}
Edit in response to comment
To find all the recipes that can be cooked, just do something like this:
List<IRecipe> results = new List<IRecipe>();
if (Pancake.CanBeMadeBy(stuff, cook)) {
results.Add(new Pancake("Yum");
}
....
Edit 2
Alternatively, if you store a list of all possible recipes somewhere, you can turn CanBeMadeBy into an instance method instead of a static, and do this:
List<IRecipe> allRecipes = // all possible recipes
...
return allRecipes.Where(r => r.CanBeMadeBy(stuff, cook));
Some ideas:
use decision tables
use the strategy pattern. This helps you to encapsulate a group of actions or parameters belonging together in different concrete classes. Once you have decided which strategy to use, you don't need any 'ifs' any more to dispatch between the strategies.
EDIT: some additional ideas:
start "small": most often, just simple refactoring to smaller, well-named, reusable functions will help you to reduce the if-else-if-else-soup. Sometimes, a simple, well named boolean variable does the trick. Both are examples for refactorings you will find in Fowler's book "Refactoring".
think "big": if you have really lot of complex business rules, constructing a "domain specific language" is an option that can sometimes be the right way of getting the complexity down. You will find lots of material on this topic just by googling for it. Citing David Wheeler All problems in computer science can be solved by another level of indirection.
ORIGIINAL POST --
Martin Fowler has solved this problem for you... its called the Specification pattern.
http://en.wikipedia.org/wiki/Specification_pattern
UPDATED POST --
Consider using the Composite Specification Pattern when:
You need to select a subset of objects based on some criteria,
You need to check that only suitable objects are used for a certain role, or
You need to describe what an object might do, without explaining the details of how the object does it
The true power of the pattern is in the ability to combine different specifications into composites with AND, OR and NOT relationships. Combining the different specifications together can be done at design time or runtime.
Eric Evan book on Domain Driven Design has an excellent example of this pattern (the Shipping Manifest)
This is the Wiki link:
http://en.wikipedia.org/wiki/Specification_pattern
At the bottom of the wiki link is this PDF link:
http://martinfowler.com/apsupp/spec.pdf
I think what that block of code is essentially trying to accomplish is linking recipes to ingredients within that recipe. One approach would be to include a list of ingredients on the recipe class itself, and then compare that against the list of ingredients passed in, like so:
public interface IRecipe {
IEnumerable<Ingredient> Ingredients { get; }
}
public class Omlette : IRecipe {
public IEnumerable<Ingredient> Ingredients {
get {
return new Ingredient[]{new Ingredient("Salt"), new Ingredient("Egg")};
}
}
}
// etc. for your other classes.
IRecipie FindRecipiesYouCanMake(IEnumerable<Ingredientes> stuff, Cook cook)
{
var query = Recipes.Where(r => !r.Ingredients.Except(stuff).Any());
return query.First();
}
This assumes that you have a collection somewhere of all your recipes. It should be simple enough to set up a static list of those or pull from a database however.
The Linq query in question looks for any recipes where all ingredients passed in stuff are present in the list of ingredients (or, as it's stated, there are no ingredients in Ingredients that are not in stuff). This also might decrease the need to have subclasses for Recipes, which seems a bit odd (although for all I know there's additional reasons you'll require this)