Linq to Entities - Three-Tier Architecture

In the past few months, I have learned a lot about Linq-To-Entities and the three-tier architecture with DAO / DAL / Repository. Now I have something that bothers me. I have three questions that you will see below.

There are many ways to make a repository work, but how is this a β€œway” to make a repository work as a way of performance.

1) Initialize datacontext in constructor

public class Repository : IRepository { private Datacontext context; public Repository() { context = new Datacontext(); } public IList<Entity> GetEntities() { return (from e in context.Entity select e).ToList(); } } 

2) Use "Use"

 public class Repository : IRepository { public IList<Entity> GetEntities() { using (Datacontext context = new Datacontext()) { return (from e in context.Entity select e).ToList(); } } } 

3) In a different way (please comment)

I will put your suggestion here for others to comment


It also seems that some people say that the repository should return the IQueryable to the business layer, while others say that it is better to return the IList. What is your attitude to this?


The above code examples in the first question point to the repository, but what is the best way to implement the repository in a business word (Initialize in the constructor, use "Use" ??)

+6
source share
5 answers

I think it works. The main thing is that you make the object contexts fairly short (IMHO). Therefore, I think you have two options: -

  • Create / destroy context in one method call, for example. using statement according to your second example.

  • Create / destroy a context when creating / destroying a repository - in this case, your repository should both implement IDisposable, and be wrapped in a using statement itself, and should be short. The advantage of this approach is that your repository methods simply execute the request, not used (new ObjectContext ()), polluting the method; flip-side is that repetition is passed to the client in order to get rid of the Repository. Using this mechanism means that you can also create queries in IQueryable <> (provided that you execute the query before deleting the repository). For instance:

Public class Repository: IDisposable {DataHubContext context = new DataHubContext ();

 public IQueryable<Payment> GetPayments() { return context.Payments; } public void Dispose() { context.Dispose(); } 

}

Formatting has become a little funny in SO - sorry .... And then in your code: -

 public class ClientCode { public void DisplayPaymentsOnScreen() { Payment[] payments; using (var repository = new Repository()) { payments = repository.GetPayments().Where(p => p.Amount > 100).ToArray(); } // Do stuff with the data here... } } 
+2
source

I think it depends on your needs ...

If your repository is intended only for receiving data, I would probably go using the "Use" method, but, to be honest, when you want a repository for receiving data. You will also want to add and update, so I would definitely go for the global data context. This can help you update the entity model and then save the changes. If you use a different data context for each call, you cannot save the changes.

The sample repository will be something like ...

 public class Repository : IRepository { private Datacontext context; public Repository() { context = new Datacontext(); } public IList<Entity> GetEntities() { return (from e in context.Entity select e).ToList(); } public void Save() { context.SubmitChanges(); } } 

... then you can make many data changes and send to the database at a time. Another thing to think about is that your GetEntities has a call to ToList (). When you call this, you are actually doing a database query. If you plan on doing further logical processing of the results, you may want to return IQueryable and only call ToList when you really need to use a list

+1
source

I would prefer to use a usage pattern, because it allows the code to be cleaner and simpler, since we know the scope of the db context and, obviously, we can tell when this is removed, which is difficult to say in the case of the constructor.

Also, I don’t think you can return IQueryable in the case of β€œuse”, since the db context will be deleted as soon as the block is out of use, and then you cannot use the returned IQueryable in your business layer.

0
source

If you want to be unable to bind your methods to make the most accurate request, use the first case. For instance:

 public class Repository : IRepository { private Datacontext context; public Repository() { context = new Datacontext(); } public IQueryabale<Entity> SelectAllEntities() { return context.Entity.Where(e=>! e.IsObsolote); } public IQueryable<Entity> SelectAllEntityRelatedToAnotherEntity(Entity otherEntity) { return this.SelectAllEntities().Where(e=>e.RelatedEntityId == otherEntity.Id); } } 

EDIT

 You can use it in collaboration with your business layer like this: public class EntityManager() { public IQueryable<Entities> FindAllApprovedEntities(Entity other) { return new Repository().SelectAllEntityRelatedToAnotherEntity(other).Where(e=>e.Approved); } } 
0
source

For me, I always return IQueryable<T>

 public IQueryable<Entity> GetEntities() { return from e in context.Entity select e; } 

You should read about delayed execution http://blogs.msdn.com/b/charlie/archive/2007/12/09/deferred-execution.aspx I use it so that I can request exact details in the business logic or user interface entity, not the whole entity (it is similar to select * )

I prefer to initialize the context in the constructor

 public class Repository : IRepository { private Datacontext context; public Repository() { context = new Datacontext(); } public IQueryable<Entity> GetEntities() { return from e in context.Entity select e; } public int Save() { // Return the number of the affected rows to determine in your code whether your query executed or not return context.SubmitChanges(); } } 

Note: Also in the design of your repository EF, make sure that all stores have one copy of the context in order to avoid errors during the update, and delete. p>

I have a common repository that I created in my company, and I plan to make it a blog in the near future, it allows you to just do a CRUD operation, and you can expand it as you want with a very small line of code. After I finish, I will update the response using the URL

0
source

Source: https://habr.com/ru/post/892482/


All Articles