Best Practices In Business Logic With Entity Framework?

asp.net c# entity-framework linq

Question

I want to know whether I am utilizing the Entity framework in the best way possible as this is the first time I have used it.

In my business logic, I have a separate class that will deal with the entity context. The issue I have is that in every video I've seen, the context is often wrapped in a using statement to ensure that it's closed, but clearly I can't do this in my business logic since the context will be closed before I can really utilize it.

So, is what I'm doing okay? Here are a few instances:

    public IEnumerable<Article> GetLatestArticles(bool Authorised) 
    {
        var ctx = new ArticleNetEntities();
        return ctx.Articles.Where(x => x.IsApproved == Authorised).OrderBy(x => x.ArticleDate);
    }

    public IEnumerable<Article> GetArticlesByMember(int MemberId, bool Authorised)
    {
        var ctx = new ArticleNetEntities();
        return ctx.Articles.Where(x => x.MemberID == MemberId && x.IsApproved == Authorised).OrderBy(x => x.ArticleDate);
    }

I simply want to make sure I'm not creating anything that will fail after being used by many of people.

1
31
5/21/2015 11:46:43 AM

Accepted Answer

It mostly relies on how you want to make your repository or data storage accessible.

I'm unsure of your meaning when you say "the context will be closed, hence I cannot execute business logic." Do your business logic by employing the sentence inside. Alternatively, if your business logic belongs to a different class, continue reading.:)

Some Repository users return concrete collections; in this case, you may include the context in the using statement.

public class ArticleRepository
{
   public List<Article> GetArticles()
   {
      List<Article> articles = null;

      using (var db = new ArticleNetEntities())
      {
         articles = db.Articles.Where(something).Take(some).ToList();
      }
   }
}

The benefit of it is that it satisfies the advice to open connections as late as possible and stop them as early as possible.

The using statement may include all of your business logic.

The drawbacks include the fact that your repository starts to understand business logic, which I personally find annoying, and the fact that you wind up using a different approach for every single situation.

The second choice - create a context and make it implement IDisposable as a component of the Repository.

public class ArticleRepository : IDisposable
{
   ArticleNetEntities db;

   public ArticleRepository()
   {
      db = new ArticleNetEntities();
   }

   public List<Article> GetArticles()
   {
      List<Article> articles = null;
      db.Articles.Where(something).Take(some).ToList();
   }

   public void Dispose()
   {
      db.Dispose();
   }

}

After that:

using (var repository = new ArticleRepository())
{
   var articles = repository.GetArticles();
}

Use insertion of dependencies instead of the third-option (my favorite). Separate all context-related activities from your repository, and leave resource disposal to the DI container:

public class ArticleRepository
{
   private IObjectContext _ctx;

   public ArticleRepository(IObjectContext ctx)
   {
      _ctx = ctx;
   }

   public IQueryable<Article> Find()
   {
      return _ctx.Articles;
   }
}

With a specified lifespan (Singleton, HttpContext, ThreadLocal, etc.), your chosen DI container will inject the concrete ObjectContext into the instantiation of the Repository and dispose of it in accordance with that setting.

I've put it up such that a fresh Context is provided for each HTTP Request. My DI container will automatically remove the context after the Request is complete.

To enable the usage of several Repositories with a single Object Context, I also utilize the Unit of Work paradigm in this situation.

I also like to return IQueryable from my Repository, as you may have observed (as opposed to a concrete List). Much more potent (but dangerous if you don't comprehend the ramifications). IQueryable is subjected to business logic by my service layer, which then provides the UI with a concrete collection.

The Unit of Work maintains the context, the Service Layer manages the business logic, and the DI container regulates the lifespan and disposal of resources/objects, making this by far the most powerful solution.

There is a lot to it, even more than this rather lengthy response, so let me know if you want more information.:)

64
10/18/2010 9:45:28 AM

Popular Answer

This code, in my opinion, is bad since it eliminates the ability to browse relationships using navigation properties.

public List<Articles>  getArticles( ){  
    using (var db = new ArticleNetEntities())
    {
        articles = db.Articles.Where(something).ToList();
    }
}

This method prevents you from using the following code because a. Members is never empty ( db context is close and cant get data automatically).

var articles = Data.getArticles();
   foreach( var a in articles ) {
       if( a.Members.any(p=>p.Name=="miki") ) {
           ...
       }
       else {
           ...
       }
    }
}

It's not a good idea to solely utilize a global database context since you need to use the remove changes method.

When you do this in your application, don't save the modifications and shut the window.

var article= globalcontext.getArticleByID(10);
article.Approved=true;

then you do an action and store it in another application point.

//..... something
globalcontext.saveChanges();

In this instance, entity framework has set the preceding article authorized attribute to changed. Upon saving, authorized is turned on.

My preferred strategy is to utilize one context per class. If necessary, you may provide context to another external procedure.

class EditArticle {

    private DbEntities de;
    private currentAricle;

    public EditArticle() {
        de = new DbEntities; //inizialize on new istance
    }

    loadArticleToEdit(Articele a){
        // a is from another context 
        currentArticle= de.Article.Single(p=>p.IdArticle==a.IdArticle){
    }

    private saveChanges(){
        ...
        pe.saveChanges();
    }
}


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow