In order to connect to a database in the ASP.NET Core Application we create a DbContext
namespace MyProject.Models
{
public class MyProjectContext : DbContext
{
public MyProjectContext (DbContextOptions<MyProjectContext> options)
: base(options){ }
public DbSet<MyProject.Models.Record> Record { get; set; }
}
}
In Startup.cs we do
public void ConfigureServices(IServiceCollection services) {
// Adds services required for using options.
//...
// Add framework services.
services.AddMvc();
services.AddDbContext<MyProjectContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MyProjectContext")));
}
And Finally in the Controller we have
namespace MyProject.Controllers
{
public class RecordsController : Controller
{
private readonly MyProjectContext _context;
public RecordsController(MyProjectContext context) {
_context = context;
}
// GET: Records
public async Task<IActionResult> Index() {
return View(await _context.Record.ToListAsync());
}
OK, all that is from the VS scaffolding...
=============================================================
I have now to do with AzureTables, so I did a test controller that does
Startup.cs
public void ConfigureServices(IServiceCollection services) {
// Adds services required for using options.
...
// Register the IConfiguration instance which "ConnectionStrings" binds against.
services.Configure<AppSecrets>(Configuration);
HelloWorldController.cs
namespace MyProject.Controllers
{
public class HelloWorldController : Controller
{
CloudTableClient cloudTableClient = null;
public HelloWorldController(IOptions<AppSecrets> optionsAccessor) {
string azureConnectionString = optionsAccessor.Value.MyProjectTablesConnectionString;
CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(azureConnectionString);
cloudTableClient = cloudStorageAccount.CreateCloudTableClient();
}
public async Task<string> ReadTables() {
CloudTable table = cloudTableClient.GetTableReference("themes");
StringBuilder response = new StringBuilder("Here is your test Table:");
var query = new TableQuery<DescriptionEntity>() {
SelectColumns = new List<string> { "RowKey", "Description" }
};
var items = await table.ExecuteQuerySegmentedAsync<DescriptionEntity>(query, null);
foreach (DescriptionEntity item in items) {
response.AppendLine($"Key: {item.RowKey}; Value: {item.Description}");
}
return response.ToString();
}
Question
How can I integrate the Azure Tables in the same way like the SQL Context does? I mean, having the same 3 steps for the Azure Tables:
Create the Azure Tables Context,
Configure Services (via ConfigureServices(IServiceCollection) in Startup.cs),
Pass the "IAzureTable context" to the Controller's constructor ?.
I am complete newbie, a code example of the steps would be greatly appreciated.
How, by eg, create the Azure DBContext (if there is a need for such one)?
According to this article(EF's roadmap), the azure table storage as EF's dbcontext database doesn't support now. It is in the high priority features and will be released in the future.
So we couldn't use the table storage as EF's dbcontext in the .net core now.
You could see the "High priority features" contains the azure table provider as below.
High priority features
Providers
Azure Table Storage
Redis
Other non-relational databases
If you want to use azure table storage in the ,net core, I suggest you could use azure storage SDK(installed from the Nuget package) and write youe own logic to CRUD the data.
Related
How can I use one DbContext with multiple application?
I have a WCF application (Net TCP binding) interface and implementation works fine with the DbContext. There is a need for API from the same application and I don't want to enable Http Binding on the WCF because of configuration and I have so many contracts. so I decided to import the service into asp.net core 2 via DI it works fine but works connect to Db via DbContext always returning null.
DB Context:
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options){}
public AppDbContext()
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(#"Server=.\;Database=Database;Trusted_Connection=True;MultipleActiveResultSets=true");
}
}
}
Service implementation
public partial class GeneralService : IGeneralService, IDisposable
{
protected readonly AppDbContext Db = new AppDbContext();
public void Dispose()
{
Db.Dispose();
}
}
Asp.net core Start Up
public void ConfigureServices(IServiceCollection services)
{
const string connection = #"Server=.\;Database=Database;Trusted_Connection=True;MultipleActiveResultSets=true";
services.AddDbContext<AppDbContext>(options => options.UseSqlServer(connection));
services.AddSingleton<IGeneralService,GeneralService>();
services.AddMvc()
.AddJsonOptions(options => options.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver());
}
what am I doing wrong, what can I do I really don't want to use Proxy
connect to Db via DbContext always returning null.
I think that might be down to the fact that you're creating the DB context directly in the service class. You can/should inject your DbContext into your service instead. Something like:
public partial class GeneralService : IGeneralService, IDisposable
{
protected readonly AppDbContext Db;
public GeneralService(AppDbContext db)
{
Db = db;
}
// ... etc...
}
Further, since you're providing a connection string to the db in your Startup.cs you don't need the OnConfiguring method in your db context.
Finally, services shouldn't be singletons if they're using EF. See this answer which recommends the Request scope.
I have the following unit of work pattern set up for an MVC 5 application using Entity Framework. The unit of work has all the repos defined as follows so that they are all using the same dbcontext and it has one save method to co-ordinate the transaction using the same context:
public class UnitOfWork : IUnitOfWork
{
private readonly ApplicationDbContext _context;
public IProductRepository ProductRepository { get; private set; }
public ICustomerRepository CustomerRepository { get; private set; }
// Other reposistories
public UnitOfWork(ApplicationDbContext context)
{
_context = context;
ProductRepository = new ProductRepository(_context);
CustomerRepository = new CustomerRepository(_context);
// Other reposistories
}
public void Complete()
{
_context.SaveChanges();
}
}
This is an example of my repo. The reason for using repos is for code re-use so that I'm not duplicating queries inside different controllers.
public class ProductRepository : IProductRepository
{
private readonly ApplicationDbContext _context;
public ProductRepository(ApplicationDbContext context)
{
_context = context;
}
public Product GetProduct(int productId)
{
return _context.Ticket.SingleOrDefault(p => p.Id == productId);
}
public void Add(Product product)
{
_context.Product.Add(product);
}
// Other methods
}
I inject the unit of work class in my controller as follows using Ninject:
public class ProductsController : Controller
{
private readonly IUnitOfWork _unitOfWork;
private readonly IFileUploadService _FileUploadService;
public ProductsController(IUnitOfWork unitOfWork,
IFileUploadService fileUploadService)
{
_unitOfWork = unitOfWork;
_FileUploadService = fileUploadService;
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CreateEditProductViewModel viewModel)
{
var product = new Product
{
// Do stuff
};
_unitOfWork.ProductRepository.Add(product);
// Call file upload service
_fileUploadService.Upload();
_unitOfWork.Complete();
}
}
This unit of work set up works fine if all I'm using are repos that are defined in the unit of work class. But now I want to use a service class to process some additional application logic and then the unit of work is committed in the controller action. If I define the class as follows it will be using a different instance of the context, In which case how would you co-ordinate a transaction where the service layers is ending up with a different context?
public class FileUploadService : IFileUploadService
{
private readonly IUnitOfWork _unitOfWork;
public FileUploadService(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public uploadResult Upload()
{
// Some stuff
var uploadedFile = new UploadedFile
{
//some stuff
};
_unitOfWork.UploadedFileRepository.Add(uploadedFile);
}
}
I've done quite a bit of research online and I'm unable to find any resource that provides a practical example to solve this problem. I've read quite a bit of stuff on ditching unit of work and repos and simply using entity frameworks dbset. However as explained above the purpose of using
repos is to consolidate queries. My questions is how do I co-ordinate the unit of work with a service class.
I would like the service to use the same context so that it can access the repositories it needs to work with, and let the controller (client code) commit the operation when it see fits.
* UPDATE *
In my DI Container I resolve all interfaces using the following snippet:
private static IKernel CreateKernel()
{
RegisterServices(kernel);
kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
// default binding for everything except unit of work
kernel.Bind(x => x.FromAssembliesMatching("*")
.SelectAllClasses()
.Excluding<UnitOfWork>()
.BindDefaultInterface());
return kernel;
}
Would adding the line kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope(); ensure that no more than one ApplicationDbContext is created, even if the request ends up hitting multiple controllers or service layers that all require an IUnitOfWork (ApplicationDbContext)?
If you are using MVC, then your unit of work is your web request. If I were you I'd ditch the UOW implementation and just make sure you dbcontext is instantiated in the Application_BeginRequest. Then I'd stuff it into the HttpContext for safe keeping. On Application_EndRequest, I dispose of the DbContext.
I would move the save to your repository.
I'd create a [Transaction] attribute that would maintain a TransactionScope something like this:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class TransactionAttribute : ActionFilterAttribute
{
private TransactionScope Transaction { get; set; }
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
Transaction = new TransactionScope( TransactionScopeOption.Required);
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.Exception == null)
{
Transaction.Complete();
return;
}
Transaction.Dispose();
}
}
You can then just tag your controller methods with [Transaction].
I'm just spitballing here, but I do something similar with NHibernate instead of EF and it works out nicely for me.
The InRequestScope() will create a new instance of the bound type on every new web request, and at the end of that web request, it will Dispose that instance if it is disposable.
I am not sure how are you passing the ApplicationDbContext into your UnitOfWork. I am assuming that you use Ninject for this injection too. Just make sure that you bind your ApplicationDbContext using the InRequestScope()Bind.To().InRequestScope();.
This way, your ApplicationDbContext instance will be created once per request and disposed at the end.
Also, the use of InRequestScope is for types that are disposable, so you can also release resoruces in the Dispose method of your UnitOfWork method too.
I am struggling with using multiple dbContext with an single web application in ASP.NET MVC 5. I am following code First existing database design approach.
so i have created dashboardModel using ADO.NET Entity model, that comes with its own dbContext (DashboardContext) and then roleModel using again ADO.net Entity Model (dbContext = RoleContext).
I want to keep similar concern of model separtate and their individual DBContext.
On creating DashboardModel, code run without problem but when i have created RoleModel and run; it gives me error on Dashboard controller ==> MetadataException was unhandled by user code
public DashboardContext()
: base("name=DashboardContext")
{
}
////
public class DashboardController : Controller
{
//
// GET: /Dashboard/
public ActionResult Home()
{
using (var db = new DashboardContext())
{
var query = from b in db.sys_Functions
orderby b.Function_ID
select b;
foreach(var item in query)
{
var a1 = item.Title;
}
}
return View();
}
}
//
public RoleContext()
: base("name=RoleContext")
{
}
//
public class TestController : Controller
{
//
// GET: /Test/
public ActionResult Index()
{
using(var db = new RoleContext())
{
var query = from x in db.AspNetRoles
orderby x.Name
select x;
foreach(var item in query)
{
var t = item.Name;
}
}
return View();
}
}
Many Thanks
I want to keep similar concern of model separtate and their individual DBContext.
DbContext is the abstraction for a database. So unless you are connecting your entities to different databases, there's no reason to use different Db contexts.
Note: this may not be so related to the question
I wanted to make two ApplicationDbContext with two different connections in ASP.NET MVC 5 (not ASP.NET CORE)
This is what worked for me, first you will need to add a second / overloaded constructor to ApplicationDbContext
Then add another ApplicationDbContext class like "ReadOnly_1_Local_ApplicationDbContext" that inherits the orignial ApplicationDbContext not the "IdentityDbContext" and make its constructor calls the overloaded base constructor with your new connection
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext() : base("<your connection>", throwIfV1Schema: false)
{
}
public ApplicationDbContext(string nameOrConnectionString) : base(nameOrConnectionString, throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
public class ReadOnly_1_Local_ApplicationDbContext : ApplicationDbContext
{
public ReadOnly_1_Local_ApplicationDbContext() : base("<your read only connection>")
{
}
}
Usage (I stopped sync from the first db to the read only one and changed the data in one of them to see it really connects to the other db)
public ActionResult TestMultiDbContext_1()
{
var db_context = new ApplicationDbContext();
return Content(db_context.Shipments.Find(123456).CustomerName); // name #1
}
public ActionResult TestMultiDbContext_2()
{
var db_context = new ReadOnly_1_Local_ApplicationDbContext();
return Content(db_context.Shipments.Find(123456).CustomerName); //name #2
}
That is tested with code first migrations and does not cause any issue and is not generating any extra migrations.
If you are adding another connection for entirely new db (not duplicated one), just make another class that inherits the IdentityDbContext normally
Thanks
Hi I have model class which is written in MVC.I am using Ef database first approach. In model class I have some queries which deals with database. I have following questions :
1) Is it right way to use database related queries in Model and call that in controller or view?
2)If yes where I should call this model? In Controller or in view ??
3)How I should call this model? Say for example I have class called class1.cs in model.How I should call this model?
Your model contains classes that define the different objects troughout your project. This includes properties with their basic information and methods to perform actions on this object.
1)
Do you really need queries? Why not use the Entity Framework to do it for you? Create the mapping for your domain classes (either trough annotations or fluent api) and use the DbContext to retrieve and save the data stored in your database
2)
Ideally people create repositories that are injected into your controllers (Dependency Injection). These repositories can for example contain something like GetPersonById(int id). Inside this method there would be two things:
Perform an action on the domain object
Save it to the DbContext
For example:
public void Subscribe(int userID, Show show) {
var user = GetUserByID(userID);
if (!user.IsSubscribedTo(show.ShowID)) {
user.Subscribe(show);
_dbContext.SaveChanges();
}
}
Controller -> Method call in repository -> Perform action on corresponding domain object -> Save changes to the database
If you need something that doesn't require an object mutation, it's even more simple:
public User GetUserByID(int id) {
return _dbContext.Users.FirstOrDefault(x => x.ID == id);
}
3)
Trough repositories (see above). Your DbContext will have a bunch of DbSets that contain objects that correspond with every data entry in your database. Trough repositories you can work with these objects and manipulate them. When you call the DbContext.SaveChanges() method, it will look at what has changed in these lists and commit the changes to your database.
Repository example:
class User {
public int ID { get; set; }
public string Name { get; set; }
}
class DatabaseContext : DbContext {
public DbSet<User> Users { get; set; }
}
public interface IUserRepository {
User GetUserByID (int id);
bool UsernameExists (string name);
}
public class UserRepository : IUserRepository {
private DatabaseContext _db;
public UserRepository(DatabaseContext db){
_db = db;
}
public User GetUserByID(int id) {
return _db.Users.FirstOrDefault(x => x.ID == id);
}
public User GetUserByUsername(string username) {
return _db.Users.FirstOrDefault(x => x.Name == username);
}
}
public class UserController : Controller {
private IUserRepository _userRepository;
public UserController(IUserRepository userRepository) {
_userRepository = userRepository;
}
public ActionResult Details(int id){
return View(_userRepository.GetUserByID(id);
}
}
// Ninject settings (install this extension, you want it):
private void AddBindings(){
kernel.Bind<DatabaseContext>().ToSelf().InSingletonScope();
kernel.Bind<IUserRepository>().To<UserRepository>().InRequestScope();
}
You could use some sort of Unit Of Work pattern which you inject in your controller constructor using an inversion of control container (IOC), for instance autofac.
Your unit of work class could hold a reference to repositories, where you would query/insert your data.
Roughly;
public class BackendController : Controller
{
private UnitOfWork _worker;
public BackendController(UnitOfWork worker)
{
this._worker = worker;
}
public ActionResult Admin()
{
var items = _worker.MyRepository.GetAll();
return View(items);
}
}
public class UnitOfWork
{
private ContentRepository _contentRepository;
public UnitOfWork()
{
}
public ContentRepository MyRepository
{
get
{
if (_contentRepository != null)
return _contentRepository;
else
return _contentRepository = new ContentRepository();
}
}
}
public class ContentRepository
{
// holds an object context and methods to retrieve and put data (EF or similar)
}
You would have to register your instance with the IOC container in global.asax, application_start for example, something like this (Using autofac as IOC):
UnitOfWork worker = new UnitOfWork();
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterInstance(worker).SingleInstance();
var container = builder.Build();
...
1) Is it right way to use database related queries in Model and call that in controller or view?
I would recommend not directly accessing the database in your model classes, as you have to remember that MVC is strictly a presentation layer pattern. If you do put your database access logic in your model classes, then you will not be able to have any other client use this functionality, such as a web service. Instead have logic that translates your business objects, defined outside of your ASP.NET MVC project, into your ASP.NET MVC model classes.
This is where the power of n-tier architecture shines, if you create a business and data-access layer, then I could write an ASP.NET MVC front-end, WebForms front-end, WPF front-end, WinForms front-end and all of them could access data using the same service. By putting the logic into the ASP.NET MVC model classes, then you are effectively forcing any other client to duplicate that logic again in their classes.
In a MVC3-application with Ninject.MVC 2.2.0.3 (after merge), instead of injecting repostories directly into controllers I'm trying to make a service-layer that contain the businesslogic and inject the repostories there. I pass the ninject-DependencyResolver to the service-layer as a dynamic object (since I don't want to reference mvc nor ninject there). Then I call GetService on it to get repositories with the bindings and lifetimes I specify in NinjectHttpApplicationModule. EDIT: In short, it failed.
How can the IoC-container be passed to the service-layer in this case? (Different approaches are also very welcome.)
EDIT: Here is an example to illustrate how I understand the answer and comments.
I should avoid the service locator (anti-)pattern and instead use dependency injection. So lets say I want to create an admin-site for Products and Categories in Northwind. I create models, repositories, services, controllers and views according to the table-definitions. The services call directly to the repositories at this point, no logic there. I have pillars of functionality and the views show raw data. These bindings are configured for NinjectMVC3:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ICategoryRepository>().To<CategoryRepository>();
kernel.Bind<IProductRepository>().To<ProductRepository>();
}
Repository-instances are created by ninject via two layers of constructor injection, in the ProductController:
private readonly ProductsService _productsService;
public ProductController(ProductsService productsService)
{
// Trimmed for this post: nullchecks with throw ArgumentNullException
_productsService = productsService;
}
and ProductsService:
protected readonly IProductRepository _productRepository;
public ProductsService(IProductRepository productRepository)
{
_productRepository = productRepository;
}
I have no need to decouple the services for now but have prepared for mocking the db.
To show a dropdown of categories in Product/Edit I make a ViewModel that holds the categories in addition to the Product:
public class ProductViewModel
{
public Product Product { get; set; }
public IEnumerable<Category> Categories { get; set; }
}
The ProductsService now needs a CategoriesRepository to create it.
private readonly ICategoryRepository _categoryRepository;
// Changed constructor to take the additional repository
public ProductsServiceEx(IProductRepository productRepository,
ICategoryRepository categoryRepository)
{
_productRepository = productRepository;
_categoryRepository = categoryRepository;
}
public ProductViewModel GetProductViewModel(int id)
{
return new ProductViewModel
{
Product = _productRepository.GetById(id),
Categories = _categoryRepository.GetAll().ToArray(),
};
}
I change the GET Edit-action to return View(_productsService.GetProductViewModel(id)); and the Edit-view to show a dropdown:
#model Northwind.BLL.ProductViewModel
...
#Html.DropDownListFor(pvm => pvm.Product.CategoryId, Model.Categories
.Select(c => new SelectListItem{Text = c.Name, Value = c.Id.ToString(), Selected = c.Id == Model.Product.CategoryId}))
One small problem with this, and the reason I went astray with Service Locator, is that none of the other action-methods in ProductController need the categories-repository. I feel it's a waste and not logical to create it unless needed. Am I missing something?
You don't need to pass the object around you can do something like this
// global.aspx
protected void Application_Start()
{
// Hook our DI stuff when application starts
SetupDependencyInjection();
}
public void SetupDependencyInjection()
{
// Tell ASP.NET MVC 3 to use our Ninject DI Container
DependencyResolver.SetResolver(new NinjectDependencyResolver(CreateKernel()));
}
protected IKernel CreateKernel()
{
var modules = new INinjectModule[]
{
new NhibernateModule(),
new ServiceModule(),
new RepoModule()
};
return new StandardKernel(modules);
}
So in this one I setup all the ninject stuff. I make a kernal with 3 files to split up all my binding so it is easy to find.
In my service layer class you just pass in the interfaces you want. This service class is in it's own project folder where I keep all my service layer classes and has no reference to the ninject library.
// service.cs
private readonly IRepo repo;
// constructor
public Service(IRepo repo)
{
this.repo = repo;
}
This is how my ServiceModule looks like(what is created in the global.aspx)
// ServiceModule()
public class ServiceModule : NinjectModule
{
public override void Load()
{
Bind<IRepo>().To<Repo>();
}
}
Seee how I bind the interface to the repo. Now every time it see that interface it will automatically bind the the Repo class to it. So you don't need to pass the object around or anything.
You don't need worry about importing .dll into your service layer. For instance I have my service classes in their own project file and everything you see above(expect the service class of course) is in my webui project(where my views and global.aspx is).
Ninject does not care if the service is in a different project since I guess it is being referenced in the webui project.
Edit
Forgot to give you the NinjectDependecyResolver
public class NinjectDependencyResolver : IDependencyResolver
{
private readonly IResolutionRoot resolutionRoot;
public NinjectDependencyResolver(IResolutionRoot kernel)
{
resolutionRoot = kernel;
}
public object GetService(Type serviceType)
{
return resolutionRoot.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return resolutionRoot.GetAll(serviceType);
}
}