Entity Framework Generic Base Class - c#

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.

Related

Should we use the entities generated by entity framework

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)

Where to put DSet DataAccess logic using Entity Framework?

I'm using CodeFirst EF6 and I'd like to place all related "queries" into a single class.
Let's say I have a
DbSet<Car> Cars;
in my DbContext.
I tried to create a new class with my concrete DbSet as base class:
public class CarRepository : DbSet<Car>
in which I'd locate all car related operations.
When I replace DbSet with CarRepository in my DbContext class it won't get filled.
I then tried to derive from IDbSet but I'm not sure how to implement all needed methods.
Is there another way to achieve this goal without using an extension class?
You can simply create your own single class(your repository) and put your methods like this.
public class Repository<TEntity> where TEntity : class
{
private DbContext context;
private DbSet<TEntity> dbSet;
public Repository(DbContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public virtual TEntity GetByID(object id)
{
return dbSet.Find(id);
}
}

How to implement FIND method of EF in Unit Test?

I have a Web API 2.0 project that I am unit testing. My controllers have a Unit of Work. The Unit of Work contains numerous Repositories for various DbSets. I have a Unity container in the Web API and I am using Moq in the test project. Within the various repositories, I use the Find method of Entity Framework to locate an entity based on it's key. Additionally, I am using Entity Framework 6.0.
Here is an very general example of the Unit of Work:
public class UnitOfWork
{
private IUnityContainer _container;
public IUnityContainer Container
{
get
{
return _container ?? UnityConfig.GetConfiguredContainer();
}
}
private ApplicationDbContext _context;
public ApplicationDbContext Context
{
get { _context ?? Container.Resolve<ApplicationDbContext>(); }
}
private GenericRepository<ExampleModel> _exampleModelRepository;
public GenericRepository<ExampleModel> ExampleModelRepository
{
get { _exampleModelRepository ??
Container.Resolve<GenericRepository<ExampleModel>>(); }
}
//Numerous other repositories and some additional methods for saving
}
The problem I am running into is that I use the Find method for some of my LINQ queries in the repositories. Based on this article, MSDN: Testing with your own test doubles (EF6 onwards), I have to create a TestDbSet<ExampleModel> to test the Find method. I was thinking about customizing the code to something like this:
namespace TestingDemo
{
class TestDbSet : TestDbSet<TEntity>
{
public override TEntity Find(params object[] keyValues)
{
var id = (string)keyValues.Single();
return this.SingleOrDefault(b => b.Id == id);
}
}
}
I figured I would have to customize my code so that TEntity is a type of some base class that has an Id property. That's my theory, but I'm not sure this is the best way to handle this.
So I have two questions. Is the approach listed above valid? If not, what would be a better approach for overriding the Find method in the DbSet with the SingleOrDefault method? Also, this approach only really works if their is only one primary key. What if my model has a compound key of different types? I would assume I would have to handle those individually. Okay, that was three questions?
To expand on my comment earlier, I'll start with my proposed solution, and then explain why.
Your problem is this: your repositories have a dependency on DbSet<T>. You are unable to test your repositories effectively because they depend on DbSet<T>.Find(int[]), so you have decided to substitute your own variant of DbSet<T> called TestDbSet<T>. This is unnecessary; DbSet<T> implements IDbSet<T>. Using Moq, we can very cleanly create a stub implementation of this interface that returns a hard coded value.
class MyRepository
{
public MyRepository(IDbSet<MyType> dbSet)
{
this.dbSet = dbSet;
}
MyType FindEntity(int id)
{
return this.dbSet.Find(id);
}
}
By switching the dependency from DbSet<T> to IDbSet<T>, the test now looks like this:
public void MyRepository_FindEntity_ReturnsExpectedEntity()
{
var id = 5;
var expectedEntity = new MyType();
var dbSet = Mock.Of<IDbSet<MyType>>(set => set.Find(It.is<int>(id)) === expectedEntity));
var repository = new MyRepository(dbSet);
var result = repository.FindEntity(id);
Assert.AreSame(expectedEntity, result);
}
There - a clean test that doesn't expose any implementation details or deal with nasty mocking of concrete classes and lets you substitute out your own version of IDbSet<MyType>.
On a side note, if you find yourself testing DbContext - don't. If you have to do that, your DbContext is too far up the stack and it will hurt if you ever try and move away from Entity Framework. Create an interface that exposes the functionality you need from DbContext and use that instead.
Note: I used Moq above. You can use any mocking framework, I just prefer Moq.
If your model has a compound key (or has the capability to have different types of keys), then things get a bit trickier. The way to solve that is to introduce your own interface. This interface should be consumed by your repositories, and the implementation should be an adapter to transform the key from your composite type into something that EF can deal with. You'd probably go with something like this:
interface IGenericDbSet<TKeyType, TObjectType>
{
TObjectType Find(TKeyType keyType);
}
This would then translate under the hood in an implementation to something like:
class GenericDbSet<TKeyType,TObjectType>
{
GenericDbSet(IDbSet<TObjectType> dbset)
{
this.dbset = dbset;
}
TObjectType Find(TKeyType key)
{
// TODO: Convert key into something a regular dbset can understand
return this.dbset(key);
}
}
I realise this is an old question, but after coming up against this issue myself when mocking data for unit tests I wrote this generic version of the 'Find' method that can be used in the TestDBSet implementation that is explained on msdn
Using this method means you dont have to create concrete types for each of your DbSets. One point to note is that this implementaion works if your entities have primary keys in one of the following forms (im sure you could modify to suite other forms easily):
'Id'
'ID'
'id'
classname +'id'
classname +'Id'
classname + 'ID'
public override T Find(params object[] keyValues)
{
ParameterExpression _ParamExp = Expression.Parameter(typeof(T), "a");
Expression _BodyExp = null;
Expression _Prop = null;
Expression _Cons = null;
PropertyInfo[] props = typeof(T).GetProperties();
var typeName = typeof(T).Name.ToLower() + "id";
var key = props.Where(p => (p.Name.ToLower().Equals("id")) || (p.Name.ToLower().Equals(typeName))).Single();
_Prop = Expression.Property(_ParamExp, key.Name);
_Cons = Expression.Constant(keyValues.Single(), key.PropertyType);
_BodyExp = Expression.Equal(_Prop, _Cons);
var _Lamba = Expression.Lambda<Func<T, Boolean>>(_BodyExp, new ParameterExpression[] { _ParamExp });
return this.SingleOrDefault(_Lamba);
}
Also from a performance point of view its not going to be as quick as the recommended method, but for my purposes its fine.
So based on the example, I did the following to be able to Unit Test my UnitOfWork.
Had to make sure my UnitOfWork was implementing IApplicationDbContext. (Also, when I say UnitOfWork, my controller's UnitOfWork is of type IUnitOfWork.)
I left all of the DbSet's in my IApplicationDbContext alone. I chose this pattern once I noticed IDbSet didn't include RemoveRange and FindAsync, which I use throughout my code. Also, with EF6, the DbSet can be set to virtual and this was recommended in MSDN, so that made sense.
I followed the Creating the in-memory test doubles
example to create the TestDbContext and all the recommended classes (e.g. TestDbAsyncQueryProvider, TestDbAsyncEnumerable, TestDbAsyncEnumerator.) Here is the code:
public class TestContext : DbContext, IApplicationDbContext
{
public TestContext()
{
this.ExampleModels= new TestBaseClassDbSet<ExampleModel>();
//New up the rest of the TestBaseClassDbSet that are need for testing
//Created an internal method to load the data
_loadDbSets();
}
public virtual DbSet<ExampleModel> ExampleModels{ get; set; }
//....List of remaining DbSets
//Local property to see if the save method was called
public int SaveChangesCount { get; private set; }
//Override the SaveChanges method for testing
public override int SaveChanges()
{
this.SaveChangesCount++;
return 1;
}
//...Override more of the DbContext methods (e.g. SaveChangesAsync)
private void _loadDbSets()
{
_loadExampleModels();
}
private void _loadExampleModels()
{
//ExpectedGlobals is a static class of the expected models
//that should be returned for some calls (e.g. GetById)
this.ExampleModels.Add(ExpectedGlobal.Expected_ExampleModel);
}
}
As I mentioned in my post, I needed to implement the FindAsync method, so I added a class called TestBaseClassDbSet, which is an alteration of the TestDbSet class in the example. Here is the modification:
//BaseModel is a class that has a key called Id that is of type string
public class TestBaseClassDbSet<TEntity> :
DbSet<TEntity>
, IQueryable, IEnumerable<TEntity>
, IDbAsyncEnumerable<TEntity>
where TEntity : BaseModel
{
//....copied all the code from the TestDbSet class that was provided
//Added the missing functions
public override TEntity Find(params object[] keyValues)
{
var id = (string)keyValues.Single();
return this.SingleOrDefault(b => b.Id == id);
}
public override Task<TEntity> FindAsync(params object[] keyValues)
{
var id = (string)keyValues.Single();
return this.SingleOrDefaultAsync(b => b.Id == id);
}
}
Created an instance of TestContext and passed that into my Mock.
var context = new TestContext();
var userStore = new Mock<IUserStore>();
//ExpectedGlobal contains a static variable call Expected_User
//to be used as to populate the principle
// when mocking the HttpRequestContext
userStore
.Setup(m => m.FindByIdAsync(ExpectedGlobal.Expected_User.Id))
.Returns(Task.FromResult(ExpectedGlobal.Expected_User));
var mockUserManager = new Mock(userStore.Object);
var mockUnitOfWork =
new Mock(mockUserManager.Object, context)
{ CallBase = false };
I then inject the mockUnitOfWork into the controller, and voila. This implementation seems to be working perfect. That said, based on some feeds I have read online, it will probably be scrutinized by some developers, but I hope some others find this to be useful.

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