Should we use the entities generated by entity framework - c#

Hello I use entity framework with a unit of work pattern and I would like to know if in my application layer I should work directly with entities generated by entity framework or recreate POCO objects in my application layer and map my POCO?
Because I would like my application layer not to make any reference to my entities, I would like for example to create another project in my solution that could map my entities to my poco in my application but I don't know if this is a good practice and especially I don't know how to do it
Thank you in advance!

In my UnitOfWork I have used a generic repository pattern that uses the models generated by the EF directly. The IRepository<T> interface looks a bit like this:
public interface IRepository<T> where T : class
{
void Add(T entity);
T GetById(long Id);
//etc - all the stuff you probably have
}
I have implementation of the IRepository called Repository
public Repository<T> : IRepository<T>
{
public readonly Infomaster _dbContext;
public Repository(Infomaster dbContext)
{
_dbContext = dbContext;
}
public void Add(T entity)
{
_dbContext.Set<T>.Add(t);
}
}
The use of the set and the type allows me to access the dataset (dbSet) of that particular type which allows me to create a generic pattern. You can use specific classes but it's a lot more work.
This means in my UnitOfWork, I only need to do the following:
public class UnitOfWork : IUnitOfWork
{
//Db context
Infomaster _dbContext;
//User is a model from my EF
public IRepository<User> UserRepository { get; private set; }
public UnitOfWork()
{
_dbContext = new Infomaster();
UserRepository = new Repository<User>(_dbContext);
}
public int Commit()
{
return _dbContext.Save();
}
}
I find that is the best way and requires the use of the model classes, I am using a code first database but I have done with database first.
(from iPhone - can and will update from laptop)

Related

Generic Repository vs Simple DbContext vs Extension Methode c#

I'm stuck in a decision that which one of these ways to use in my project.
Project is asp.net core mvc and layers are shown at this image(just to clear what i am looking for)
At first I used generic Repository Pattern for this project and codes are this
public interface IGenericRepository<TEntity> : IDisposable where TEntity:BaseModel
{
IQueryable<TEntity> GetEntitiesQuery();
Task<TEntity> GetEntityById(long entityId);
Task<TEntity> GetEntityByIdAsNoTracking(long entityId);
Task AddEntity(TEntity entity);
void UpdateEntity(TEntity entity);
void SoftRemoveEntity(TEntity entity);
Task SoftRemoveEntityById(long entityId);
void HardRemoveEntity(TEntity entity);
Task HardRemoveEntityById(long entityId);
Task SaveChangesAsync();
}
Its worked perfectly but I read that this generic repository pattern is old these days and also there is a problem when I want to use some entities in one service I have to inject each entity separately on my service which makes this harder on my test project.
Imagine this scenario that in my AccountService.cs on Register method I want to modify 4 entity User-Role-Log-Score so my constructor would be like this :
public class AccountService : IAccountService
{
private readonly IGenericRepository<User> _userRepository;
private readonly IGenericRepository<Role> _roleRepository;
private readonly IGenericRepository<Log> _logRepository;
private readonly IGenericRepository<Score> _scoreRepository;
public AccountService(IGenericRepository<User> userRepository, IGenericRepository<Role>
roleRepository, IGenericRepository<Log> logRepository, IGenericRepository<Score>
scoreRepository)
{
_userRepository = userRepository;
_roleRepository = roleRepository;
_logRepository = logRepository;
_scoreRepository = scoreRepository;
}
So this is huge and I do not think that is a good Idia to use something like this so I have 2 other options one is use DbContext directly without no Repositoy at all and one more way is using extension Methodes for DbContext like this
public static class DbContextExtension
{
public static IQueryable<TEntity> GetEntitiesQuery<TEntity>(this MainDbContext
dbContext) where TEntity : BaseModel
{
return dbContext.Set<TEntity>().AsQueryable();
}
public static async Task AddEntity<TEntity>(this MainDbContext dbContext, TEntity
entity) where TEntity : BaseModel
{
entity.CreateDate = DateTime.Now;
entity.LastUpdateDate = entity.CreateDate;
await dbContext.Set<TEntity>().AddAsync(entity);
}
}
If I use this way I only inject my dbContext once and I use every entity I want
So now Help me which way is better in performance and everything? which one do you suggest ? and why?
1: Generic Repository
2: DbContext Without Repository and unit of work
3: Extension Methode
Using IOC container to register all IRepositories as singletons,this is a good way to layer the modules. Each IPocoRepository should contain the common CURD APIs and it's unique business APIs.
PS: I don't like the generic solution.

Entity Framework Generic Base Class

I have no choice in creating a data first Entity Framework implementation. I want to extend the generated class to include a generic base class that I can call all the basic functions on. (I know how to update the t4 templates)
Update (add if not currently in DB), GetAll, Select (based on parameters) and Delete functions. I have found a few things that I think may work but they do not have fully qualified namespaces and I can't figure out where the information is stored.
Creating base class for Entities in Entity Framework - is one such which is basically a duplicate of my question but the answers are not complete.
What would be an example of this base class WITH the fully qualified namespace?
You can still use Code First even though you have a database. You can generate your model. Depends what you need, please see 2 different ways to approach the problem.
Generic repository
public abstract class BaseRepository<TEntity> where TEntity : class
{
protected DbContext context;
protected BaseRepository(MyDbContext context)
{
this.context = context;
}
public List<TEntity> GetAll()
{
// Set<TEntity> provides you an access to entity DbSet
// Just like if you call context.Users or context.[AnyTableName]
return context.Set<TEntity>().ToList();
}
}
Next you want to implement entity-specific repositories:
public class UserRepository : BaseRepository<User>
{
public UserRepository(MyDbContext context) : base(context)
{
}
}
Simple usage example:
using (var context = new MyDbContext())
{
var userRepository = new UserRepository(context);
var users = userRepository.GetAll();
}
Just put your generic methods in context
public class MyContext : DbContext
{
public DbSet<User> Users { get; set; }
// ... more DbSets
public List<TEntity> GetAll<TEntity>() where TEntity : class
{
return Set<TEntity>().ToList();
}
// For entities that implement INamedEntity interface
// with property Name.
public TNamedEntity FindByName<TNamedEntity>(string name)
where TNamedEntity : INamedEntity, class
{
return Set<TNamedEntity>()
.FirstOrDefault(entity => entity.Name == name);
}
}
I use nuget package EntityFramework. DbContext and DbSet comes from System.Data.Entity namespace.
Hope it's enough for you to get started and implement all the methods that you need.

Trying to understand Repository Pattern with EF6

I am currently implementing EF6 to replace the ADO connection that currently exists.
I have read articles on why I should/shouldn't use the Repository pattern.
However I'm still not sure how to correctly call the repository pattern.
My project is layered as:
Presentation
Business Layer
Business Objects
Data Access Layer
Web Services
In the DAL I add my EF6 connection to my DB.
I created a IRepository and Repository classes.
Should the Business Layer be the one to call the Repository class?
If so I'm missing the connection here on how to call it.
Repository class:
public class MyRepository<T> : IRepository<T> where T : class
{
protected DbSet<T> DbSet;
protected DbContext _context;
public MyRepository(DbContext dataContext)
{
_context = dataContext;
DbSet = dataContext.Set<T>();
}
#region IRepository
public int Save()
{
return _context.SaveChanges();
}
public void Insert(T entity)
{
DbSet.Add(entity);
}
public void Delete(T entity)
{
DbSet.Remove(entity);
}
public IQueryable<T> SearchFor(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
return DbSet.Where(predicate);
}
public IQueryable<T> GetAll()
{
return DbSet;
}
public T GetById(int id)
{
return DbSet.Find(id);
}
#endregion
}
My goal is to have MyRepository handle the 6 or so tables that I added in EF.
Where I am missing is how to implement this class in my business access layer.
I get the error
'MyEFConn' is a 'type' but is used like a 'variable'
My attempt at implementing it is:
MyRepository<"table from EF"> users = new MyRepository<"table from EF">(MyEFConn);
Which MyEFConn is my DbContext class..
public partial class MyEFConn: DbContext
I get the error 'MyEFConn' is a 'type' but is used like a 'variable'
This is because the constructor for MyRepository expects to be passed an instance of a DbContext. In your case that would be an instance of MyEFConn.
Ex:
MyEfConn context = new MyEfConn();
MyRepository<MyUsers> users = new MyRepository<MyUsers>(context);

DbSet outside of DbContext class

My project has couple of Areas which each one of them has their own entities and I'm trying to keep everything isolate in that area... (lets call those areas = plugins)
DbContext
public class PortalDbContext : DbContext, IUnitOfWork
{
public new IDbSet<TEntity> Set<TEntity>() where TEntity : class
{
return base.Set<TEntity>();
}
}
IUnitOfWork
public interface IUnitOfWork
{
int SaveChanges();
IDbSet<TEntity> Set<TEntity>() where TEntity : class;
}
Service.cs
public class PageService : IPage
{
public readonly IUnitOfWork _uow;
public readonly IDbSet<Pages> _page;
public PageService(IUnitOfWork uow)
{
_uow = uow;
_page = uow.Set<Pages>();
}
}
Finally When I try:
public void AddPage(PageModel m)
{
_page.Add(m);
}
I get this error:
The entity type Pages is not part of the model for the current context
this means uow.Set<Pages>(); doesn't worked properly.
is it possible to DbSet out of DbContext class is ASP.Net MVC code first?
Actually, this error message
The entity type Pages is not part of the model for the current context
means, that the type PageModel was not configured as an entity type for the PortalDbContext context instance. You should either follow conventions to build your model (see this page, "Type Discovery" paragraph), or build model manually, using fluent API.
The second scenario fits dynamic models for plugin-based applications, because you can discover models types, using custom algorithm, and call DbModelBuilder methods to "assembly" model.
is it possible to DbSet out of DbContext class is ASP.Net MVC code first?
In short, you can't use DbSet<TEntity> without DbContext.
Consider DbSet as a part of context (AFAIK, DbSet holds a reference to DbContext, which was used to create DbSet).
Since ASP .NET is all about stateless, usual approach is to create DbContext instance (or its unit-of-work-like wrapper), perform an action, dispose the context, and throw it away. Holding references to DbContext/DbSet as a state in web applications at least useless.

using UnitOfWork and Repository Pattern with Entity Framework

I'm gonna to use repository and UnitOfwork in my data access layer to do this take a look at one contact aggregateroot
public interface IAggregateRoot
{
}
this is my Generic repository interface :
public interface IRepository<T>
{
IEnumerable<T> GetAll();
T FindBy(params Object[] keyValues);
void Add(T entity);
void Update(T entity);
void Delete(T entity);
}
and my POCO Contact class in Model
public class Contact :IAggregateRoot
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Title { get; set; }
public string Body { get; set; }
public DateTime CreationTime { get; set; }
}
and this my IContactRepository that inherit from IRepository and also maybe has it is own method
public interface IContactRepository : IRepository<Contact>
{
}
Now I have done in IUitOfWork and UnitOfwork like this
public interface IUnitOfWork
{
IRepository<Contact> ContactRepository { get; }
}
public class UnitOfWork : IUnitOfWork
{
private readonly StatosContext _statosContext = new StatosContext();
private IRepository<Contact> _contactUsRepository;
public IRepository<Contact> ContactRepository
{
get { return _contactUsRepository ?? (_contactUsRepository = new Repository<Contact>(_statosContext)); }
}
}
also about my Repository
public class Repository<T> : IRepository<T> where T : class, IAggregateRoot
{
//implementing methods
}
I can do all CRUD operation with accessing Repositories with UnitOfwork in Service , example :
_unitOfWork.ContactRepository.Add(contact);
_unitOfWork.SaveChanges();
but I want to do like this
_
ContactRepository.Add(contact);
_unitOfWork.SaveChanges();
(get CRUD and generic method via _ContactRepository No by _unitOfWork.ContactRepository)
Because I want to get ContactRepository method to some specific queries ,
anybody help please ??
It's not a direct answer to your question, but it might simplify things a little bit and reduce duplication.
When you use e.g. EntityFramework Power Tools to reverse-engineer Code First (or just use Code First in general), you end up with the DbContext class that serves as a UoW and repository in one, e.g.:
public partial class YourDbContext : DbContext
{
public DbSet<Contact> Contacts {get; set;}
}
Now, if you want things to be testable, there's an easy way: introduce a very thin interface:
public interface IDbContext
{
IDbSet<T> EntitySet<T>() where T : class;
int SaveChanges();
//you can reveal more methods from the original DbContext, like `GetValidationErrors` method or whatever you really need.
}
then make another file with second part of the partial class:
public partial class YourDbContext : IDbContext
{
public IDbSet<T> EntitySet<T>() where T : class
{
return Set<T>();
}
}
Ta-da! Now you can inject IDbContext with YourDbContext backing it up:
//context is an injected IDbContext:
var contact = context.EntitySet<Contact>().Single(x => x.Id == 2);
contact.Name = "Updated name";
context.EntitySet<Contact>().Add(new Contact { Name = "Brand new" });
context.SaveChanges();
Now if you want to have control over the disposal of the context, then you'd have to write your own (gasp) IDbContextFactory (generic or not, depending what you need) and inject that factory instead.
No need to write your own Find, Add or Update methods now, DbContext will handle that appropriately, it's easier to introduce explicit transactions and everything is nicely hidden behind interfaces (IDbContext, IDbSet).
By the way, the IDbContextFactory would be an equivalent to NHibernate's ISessionFactory and IDbContext - ISession. I wish EF had this out of the box, too.
I agree with the Doctor, DbContext is already a UnitOfWork, and adding another UoW abstraction on top of it is typically redundant, unless you think it's highly likely you might switch database technologies in the future.
I don't agree, however, with treating DbSet's as repositories, since this tightly couples your queries to the methods that use them. If you need to change a query, you have to do it everywhere you use it.
I prefer to either use a stand-alone repository (or service interface, they serve similar functions) or to use more of a CQRS system for Command/Query Seperation, an use query objects.
Inside the UnitOfWork class you need to implement DBContext or ObjectContext.
UnitOfWork segregates all transactions regardless of the system. EF is only for DB connection. Even if your system is only using DB still it is better to keep a separate UnitOfWork class for future expansions.
And inside the unit of work Commit(), you can call the internally implemented DBContext.SaveChanges().
This DBcontext will be accessible to all repositories declared inside unitofwork. So repositories add or delete from DBcontext and unitOfwork commits it.
When you have scenarios spanning different storages eg: Cloud Blobs, table storage etc. You could implement them inside UnitofWork just like you implemented a EF context. And some repositories can access Table Storage and some EF context.
Tip: Implementing ObjectContext instead of DBContext gives you an edge in caching scenarios. And you have more options in extending your framework.

Categories

Resources