Repository does not initialize entity data - c#

I would like to create a Details view with entity framework data using a repository pattern.
This is my interface repository:
public interface InterfaceRepositroy: IDisposable
{
IEnumerable<SubjectContent> GetAll();
SubjectContent Get(string id);
}
This is the toher repository:
public class SubjectRepository : InterfaceRepositroy,IDisposable
{
private irfwebpage20161013070934_dbEntities2 db;
public IEnumerable<SubjectContent> GetAll()
{
return db.Set<SubjectContent>().ToList();
}
public SubjectContent Get(string id)
{
return db.Set<SubjectContent>().Find(id);
}
public void Dispose()
{
throw new NotImplementedException();
}
}
Here is my controller:
private InterfaceRepositroy subjectreposi;
public ActionResult Details(string id)
{
SubjectContent subject = subjectreposi.Get(id);
return View(subject);
}
My View is a standard details template.
It gets an error at this point in the controller:
SubjectContent subject = subjectreposi.Get(id);
I would really appreciate the help. This is like the fourth version of a repository pattern i am trying to implement but none of them worked so far. I have tried it without interface, with the instance of the subjecrepository or with different linq to sql in the repository. It either gets http error or it doesnt show the data just the names of the data.

Create constructors that initialise your data context:
public SubjectRepository()
{
db = new irfwebpage20161013070934_dbEntities2();
}
public SubjectRepository(irfwebpage20161013070934_dbEntities2 dbContext)
{
db = dbContext;
}
This allows you to either initialise your repository with no parameters which will initialise you data context or specify your own data context.
You can now use this like this:
var repo = new SubjectRepository();
SubjectContent subject = repo.Get(id);

Related

Dependency Injection of DbContext with Dynamic ConnString

Below is a simple but functional example of roughly how I would do Dependency Injection. This works great when my DbContext connection string is not dynamic. Even if it's passed in to the factory through a config file or whatever, it doesn't matter so long as it's the same one all the time.
What I need is to wrap my head around how to make (ideally minor) modifications to the below code to allow for the connection string to be determined dynamically at run time.
For example, say on the View the user was able to not only select the teacher to be passed into the Post method of the controller, but also the school. If, for simplicity sake, there are 2 schools that have the exact same database structure, but have different connection strings how do I get that down from the controller to the factory?
I've experimented with passing a value from method to method, but this isn't really sustainable for large projects, increases the likelihood of errors and overall is just messy (besides violations of SOLID) to be passing something from layer to layer like that. (If desired I can add the not exactly ideal attempts I've made, I've omitted them for brevity sake since this is already a fairly long question what with the code examples and all).
Controller
public class HomeController : Controller
{
private readonly IDataService _dataService;
public HomeController(IDataService dataService)
{
_dataService = dataService;
}
public ActionResult Index()
{
var results = _dataService.GetTeachers();
var model = new ViewModel
{
Teachers = results
};
return View(model);
}
[HttpPost]
public ActionResult Index(ViewModel model)
{
var results = _dataService.GetCourses(model.Teacher);
model.Courses = new List<string>(results);
return View(model);
}
}
Service
public class DataService : IDataService
{
private readonly IDataRepo _dataRepo;
public DataService(IDataRepo dataRepo)
{
_dataRepo = dataRepo;
}
public List<string> GetCourses(string teacherName)
{
return _dataRepo.GetCourses()
.Where(c => c.Teacher.FirstName == teacherName)
.Select(c => c.Name)
.ToList();
}
public List<string> GetTeachers()
{
return _dataRepo.GetCourses()
.Select(c => c.Teacher.FirstName)
.ToList();
}
}
Repository
public class DataRepo : IDataRepo
{
private readonly SchoolContext _context;
public DataRepo()
{
_context = ContextFactory.MakeContext();
}
public IEnumerable<Course> GetCourses()
{
return _context.Courses;
}
}
Context Factory
public static class ContextFactory
{
public static SchoolContext MakeContext()
{
var connString =
"connStringA";
return new SchoolContext(connString);
}
}
UnityConfig
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType<IDataService, DataService>();
container.RegisterType<IDataRepo, DataRepo>();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
First, you have to decide how are you going to get the current connection string to use. Is it through a URL? or using the current user or whatever other way.
Then, create another database that has a mapping between the connection strings and the method you chose (user, url ...)
Lastly, implement a way to get the record from the database.
so, assuming that you will use the URL as an identifier for the current tenant, your entity class should be like this:
public class Tenant
{
public string Url {get;set;}
public string ConnectionString {get;set;}
}
An interface that represents the logic to get the current tenant:
public interface ICurrentTenantService
{
Tenant GetCurrentTenant();
}
And now you will put its implementation
public class CurrentTenantService : ICurrentTenantService
{
public Tenant GetCurrentTenant()
{
string currentUrl = HttpContext.Current.Url; //make sure to get only the base URL here
return TenantDbContext.Tenants.FirstOrDefault(t=>t.Url == url); //TenantDbContext should be a class that has the Tenant entity
}
}
Now you have to wire up the context factory to the tenant service like this
public static class ContextFactory
{
private readonly ICurrentTenantService currentTenantService;
//Inject it in the constructor
public static SchoolContext MakeContext()
{
var currentTenant= currentTenantService.GetCurrentTenant(); //Check for NULL
return new SchoolContext(currentTenant.ConnectionString);
}
}

Initializing objects using this operator in constructors

As I was trying to implement code first approach using repository patterns in MVC, I have come across some difficulties as below:
I have a Interface that have few methods declared as below :
public interface IRepository
{
User Getuserdetail(int UserId);
void Save(User Obj);
void delete(int Userid);
void update(User user);
}
Then I have a Repository class which could be using the above interface to define all the methods and will create a seperate layer of Entity Framework:
public class Repository : IRepository
{
RepoDBContext _context;
Repository(RepoDBContext Context)
{
this._context = Context;
}
public User Getuserdetail(int Userid)
{
var user = _context.User.Where(m => m.id == Userid).FirstOrDefault();
return user;
}
public void Save(User user)
{
_context.User.Add(user);
_context.SaveChanges();
}
}
Now could you please check the constructor of this class. The variable this constructor is initializing is type of "RepoDBContext" and the reference type it is using to assign it is also of "RepoDBContext". Is it internally performing like below?
RepoDBContext _context=new RepoDBContext();
My RepoDBContext class is below:
public class RepoDBContext : DbContext
{
public DbSet<User> User { get; set; }
}
Moreover if is the right way to perform then how will i have to call this class in my controller to do some functionality over my user interface. Please guide regarding the same and please don't mind my english. Thanks
I think you already have an answer to the question does assigning a parameter to a field is equivalent to instantiating a new instance of that type as state in the comments and in the answer by Oskar and Kirk.
But I just want go further and try to answer this another question of yours: how will I have to call this class in my controller to do some functionality over my user interface..
If you create your structure using the Repository pattern, you wouldn't want your controllers to handle instances of your DbContext class, because if they do, what is the benefit of having a separated repository layer then? A common pattern that I see people using and I use it myself in several apps is something as follows:
IUserRepository
public interface IUserRepository
{
User GetUserDetail(int userId);
void Save(User user);
void Delete(int userId);
void Update(User user);
}
UserRepository
public class UserRepository : IUserRepository
{
public User GetUserDetail(int userId)
{
using(var _context = new RepoDBContext())
{
return _context.User.Where(m => m.id == userId).FirstOrDefault();
}
}
//other implementations here..
}
Then, you create another layer which will be your Business layer, similar to the Repository.
IUserBusiness
public interface IUserBusiness
{
User GetUserDetail(int userId);
void Save(User user);
void Delete(int userId);
void Update(User user);
}
UserBusiness
public class UserBusiness : IUserBusiness
{
private readonly IUserRepository userRepository;
//CTOR receives a Repository instance via DI
public UserBusiness(IUserRepository userRepository)
{
this.userBusiness = userBusiness;
}
public User GetUserDetail(int userId)
{
//Call repository to get User details
return this.userRepository.GetUserDetail(userId);
}
//other implementations here
}
UserController (example)
public class UserController : Controller
{
private readonly IUserBusiness userBusiness;
//Controller receives a UserBusinnes instance via DI
public UserController(IUserBusiness userBusiness)
{
this.userBusiness = userBusiness;
}
public ActionResult GetDetail(int userId)
{
//Call your "repository" to get user data
var userDetail = userBusiness.GetUserDetail(userId);
//more logic here
}
}
See the difference? Each layer of your application is concerned with one thing. You controller request data to your business layer, which may apply some business rules or validations, and finally call your repository layer which knows how to talk to the database or other storage. Your controller doesn't have any concern about how to create instances of database class or make queries. It just receive a request, ask for data and returns back to the caller.
No, assigning an existing instance of RepoDBContext to a variable is NOT the same as calling new RepoDBContext(). Assignment is just assignment and will not allocate new objects.
Off-topic:
Please also consider that C# coding guidelines suggest that method parameters should be named likeThis (that is, with initial lower case letter). This will make you code more consistent with other .Net code libraries.

What are better alternatives in asp.net MVC to directly accessing the database in the Controller?

Normally I do my data access by instanciating my DbContext globally in my Controller and then I use that manipulate my data.
See below:
public class UserController : Controller
{
private OrtundEntities db = new OrtundEntities();
public ActionResult Create(CreateUserViewModel model)
{
try
{
UserDataModel user = new UserDataModel
{
// map view model fields to data model ones
};
db.Users.Add(user);
db.SaveChanges();
}
catch (Exception ex)
{
// some or other error handling goes here
}
}
}
It occurs to me that this might not be the ideal way to do it in all applications but aside from implementing a web service for every project I do, I can't think of any alternatives to the above.
So what's a better way to handle the data access on larger projects where the above wouldn't be ideal?
I'm just looking for so-called "best practice" for this or that particular situation. Many opinions will differ on what's the best way so what do you think it is and why?
To help keep your controllers concise and free of direct access to your database, you can implement the repository and dependency injection patterns. For even more concise code, you can also use the unit of work pattern.
Say you had this model:
public class Person {
public int Id { get; set; }
public string Name { get; set; }
}
With the help of generics, you can create an interface to provide a CRUD blueprint:
public interface IRepository<T> {
IEnumerable<T> Get();
T Get(int? i);
void Create(T t);
void Update(T t);
void Delete(int? i);
}
Then create a Repository class that implements the IRepository. This is where all your CRUD will take place:
public class PersonRepository : IRepository<Person> {
private OrtundEntities db = new OrtundEntities();
public IEnumerable<Person> Get() {
return db.Persons.ToList();
}
//invoke the rest of the interface's methods
(...)
}
Then in your controller you can invoke the dependency injection pattern:
private IRepository<Person> repo;
public PersonController() : this(new PersonRepository()) { }
public PersonController(IRepository<Person> repo) {
this.repo = repo;
}
And your controller method for, say, Index() could look like this:
public ActionResult Index() {
return View(repo.Get());
}
As you can see this has some useful benefits, including structure to your project, and keeping your controllers easy to maintain.
I think you need to read this
http://chsakell.com/2015/02/15/asp-net-mvc-solution-architecture-best-practices/
Larger proyets ?
Maybe https://msdn.microsoft.com/es-es/library/system.data.sqlclient.sqlcommand(v=vs.110).aspx
I use this in some big requests.

ASP.NET universal controller for database dictionaries (using Entity Framework)

I've got some models that only have two fields: Id and Name. All this models inherit from IDbDictionary interface.
My goal is to make "universal" controller for CRUD operations for this models. My problem is how to (using EF) modify database table by name. For example, there is method
[HttpPost]
public ActionResult Create(IDbDictionary newRecord, string collectionName)
{
if (ModelState.IsValid)
{
db.<collectionName>.Add(newRecord);
db.SaveChanges();
return View("Success");
}
return View("Create", newRecord);
}
Is there a way to do it the way I described? I thought about reflection, but I've no idea how to do this.
Regards,
C
Usually you would have a Service that would handle your generic database operations which you can call from all your methods. Example:
public class DataService
{
public readonly ApplicationDbContext dbContext;
public DataService(ApplicationDbContext dbContext)
{
this.dbContext = dbContext;
}
public void Create<TEntity>(TEntity entity) where TEntity : IDbDictionary
{
this.dbContext.Set<TEntity>().Add(entity);
this.dbContext.SaveChanges();
}
}
Then in your method you would use:
var dataService = new DataService(this.dbContext);
dataService.Create<ClassName>(newEntity);

Global variables can use in dbcontext scope

I want to access some data within my overriden SaveChanges() in my dbcontext without passing any parameters. Any suggestions? I'm working with MVC4 and Entity Framework Database-First.
public partial class Entities : DbContext
{
public override int SaveChanges()
{
// i want to get user info from MVC model but no need to pass any parameters when call SaveChanges()
var UserInfo = userInfo;
// Call the original SaveChanges(), which will save both the changes made and the audit records
return base.SaveChanges();
}
}
Solution 1: Dependency Injection
This solution is pretty extensible, but you would have to modify the code in your repositories and controllers to use the injected dependencies instead of creating new instances with new.
Install Ninject. In Visual Studio, find the Package Manager Console and run Install-Package Ninject.MVC4 -dependencyVersion Highest in there.
Add constructor injection. Modify your controller, so that it gets an instance of your repository in its constructor. Modify your repository, so that it gets an instance of your entity context in its constructor. Cache your dependencies in private fields. Example code:
// In your controller:
public MyController(MyRepository repo)
{
this.repo = repo;
}
// In your repository:
public MyRepository(Entities context)
{
this.context = context;
}
// In your entities:
public Entities(UserInfo userInfo)
{
this.userInfo = userInfo;
}
Add a UserInfo provider. We need to tell Ninject where to get the UserInfo from. We can use the provider interface here:
public class UserInfoProvider : Provider<UserInfo>
{
protected override UserInfo CreateInstance(IContext context)
{
UserInfo UserInfo = new UserInfo();
// Do some complex initialization here.
return userInfo;
}
}
Add bindings. We need to tell Ninject to use the provider. We also want the lifetime of a UserInfo instance and of our entity context to be bound to the request cycle of MVC. Update your App_Start\NinjectWebCommon.cs:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<Entities>()
.ToSelf()
.InRequestScope();
kernel.Bind<UserInfo>()
.ToProvider<UserInfoProvider>()
.InRequestScope();
}
Run your app. Ninject should use your constructors and provide the requested dependencies.
For further information, visit the Ninject Wiki.
Solution 2: Thread local context
This requires no modification to your repositories, but it makes the code less testable and resembles an anti pattern somehow. This won't work if your controller calls multithreaded code.
Add context class.
public class UserInfoContext : IDisposable
{
private static readonly ThreadLocal<UserInfo> UserInfos = new ThreadLocal<UserInfo>();
public static UserInfo Current
{
get
{
if (UserInfos == null)
{
throw new InvalidOperationException("UserInfoContext has not been set.");
}
return UserInfos.Value;
}
}
public static UserInfoContext Create(UserInfo userInfo)
{
if (userInfo == null)
{
throw new ArgumentNullException("userInfo");
}
if (UserInfos.Value != null)
{
throw new InvalidOperationException("UserInfoContext should not be nested.");
}
UserInfos.Value = userInfo;
return new UserInfoContext();
}
private UserInfoContext() { }
public void Dispose()
{
UserInfos.Value = null;
}
}
Wrap your controller code. Example:
public ActionResult Index()
{
using (UserInfoContext.Create(myUserInfo))
{
// do stuff that calls your repositories
return View();
}
}
Update your Entities class.
public partial class Entities : DbContext
{
public override int SaveChanges()
{
var UserInfo = UserInfoContext.Current;
// Call the original SaveChanges(), which will save both the changes made and the audit records
return base.SaveChanges();
}
}

Categories