I'm new to MVC4 framework & been working on an Licensing application that must use different databases for different products (each database contains handful tables for one product - all generated by proprietary licensing tool). My application shall be able to support CRUD functions on various products, thus requiring more than one DbContext objects in relation to different model for each product.
As far as I know, each such DbContext object requires a connection string in the Web.config file. I'm struggling to list (Index.cshtml) existing licences for various products, using DropDownList control, as for each product I'd need to connect to a different database whenever the user choose a different product from the DropDownList control.
Any help will be highly appreciated. Thanks.
As I understand your question, the core issue is you are struggling to connect to a different db, whenever user selects a different product from a DropDownList. As you said, yes DbContext object requires a connection string in the Web.config file. You can specify multiple connection strings in a config.
Also you can definitely pass different connection strings to DBContext constructor. Typically your DAL/Data Access Layer or Repository layer would pull appropriate connection string from the Web.Config/App.config and pass it to the DBContext constructor. See a similar approach here and here.
UPDATE :
You cannot share the same DbContext with multiple databases. You need multiple DbContexts for each of your DB.
Additional
There are few of doing this, but if you use Repostory and Unit Of Work pattern, you can use an approach like this
Each DbContext you going to have, you can associate with set of entities within that database in context. Something like below
public class ProductContext : DbContext
{
public ProductContext ()
: base("connectionStringA")
{
}
public DbSet<Product> Accounts { get; set; }
}
public class LicenceContext : DbContext
{
public LicenceContext ()
: base("connectionStringB")
{
}
public DbSet<Licence> Licenses{ get; set; }
}
Related
I'm using ASP.NET Core MVC 2. I need to operator can change some elements of Models or view codes. How I can code or design for it.
For example: I have a "news" model and I want to operator (final user of website, who can't code or access to visual studio) can add this to "news" model:
public string ImageUrl { get; set; }
and also can change the database without coding.
Thanks
If you want to design a completely extensible model, you could use something called Entity–attribute–value model (EAV).
Your model might have a couple common attributes like Title and Summary. Then you might have a list of Custom Fields, the first of which could be ImageUrl. You could create your own class called CustomField or something similar, which would have properties such as FieldName, and DataType.
public string Title { get; set; }
public string Summary { get; set; }
public List<CustomField> CustomFields { get; set; }
You would then have a table full of custom field values and the tables they belong to. It gets pretty complex.
When you want to automatically reflect your model changes to the database, you will need an ORM framework like EF (Entity Framework). You can check more here.
In order for your case to happen is to build your own configuration platform that may use several tools and mechanincs that will allow you to generate code and then compile it. Such as T4 and more.
In general, this is a very hard task to accomplish and even big experienced teams would have troubles to build something similar.
I can not post any code, as this would only seem a desperate approach.
Currently I am building a web application with MVC 4 and Entity Framework code first scenario.
In the main structure of my application, I have a Dbcontext(BlogDB) to manage some Blog classes. It works fine as it created all the tables I need in the database. Then I created a Area to host an online store. My idea is to create a separated DbContext class(OnlineStoreDB) to handle the classes used for Online Store only.
My problem is once the OnlineStoreDB is fired, entity framework not only created tables for OnlineStore BUT ALSO removed old tables.
My questions are:
If you know a way to keep the old tables?
How exactly to manage the multi EF context classes in one application?
Code:
public class BlogDB : DbContext
{
public BlogDB ()
: base("DBConnection")
{
Database.SetInitializer(new BlogInitializer());
}
public DbSet<Blog> Blogs { get; set; }
public DbSet<Author> Authors { get; set; }
public DbSet<Comment> Comments { get; set; }
}
public class OnlineStoreDB : DbContext
{
public OnlineStoreDB() :
base("DbConnection")
{
Database.SetInitializer(new OnlineStoreInitializer());
}
public DbSet<Order> Orders { get; set; }
public DbSet<Product> Products { get; set; }
public DbSet<User> Users { get; set; }
}
Xavier, welcome to code-first!
Yes, code-first was a brilliant approach that promised soooo much. But now you've hit the catch. There's no clever mind at Microsoft (or outside as far as I know) who has come up with a smooth way to alter tables intelligently without endangering the data and possibly schema.
2 Years ago, the implementation strategy was to drop and re-build the DB. That was just intolerable as many of us didn't have SU access and were stopped in our tracks.
For all the advantages I found from code first, I prefer DB first. While data can't be preserved easily, annotations can through buddy classes.
Microsoft has come up with some clever Migration Strategies. I strongly suggest you read both articles. Code Project 2nd:
1) http://blogs.msdn.com/b/adonet/archive/2012/02/09/ef-4-3-code-based-migrations-walkthrough.aspx
2) http://www.codeproject.com/Articles/504720/EntityplusFrameworkplusCodeplusFirstplusMigrations
whether you decide to continue with Code-First, they should be enlightening. I sound like a critic but I'm torn between advantages of one and stability of the other.
Finally, I don't think you should preserve 2 dbcontexts. Your POCOs should be consolidated under 1 context.
If you want to keep the tables not changed you need to set initializer to null in both DBContexts if they have sub set of tables .
But I don't see a point that you create two DBContexts for one database. Can you clearly separate two set of tables(Domains) in you database?
Im using Entity Framework 4 with code first. I have a model and i want to be able to map this model to a different table in the database based on a configuration file.
Example model:
public class Statistic
{
[Key]
public int id { get; set; }
public string jobName { get; set; }
public DateTime date { get; set; }
public int pages { get; set; }
}
Each customer has a configuration file where the table name that should be used is specified. So each customer should then have its own table (in the same database) with the model above.
How can i do this with Entity Framework 4?
I tried this in my DbContext:
modelBuilder.Entity<Statistic>().ToTable(tabelName);
But what EF does when i use this is to change the existing table name to the new tableName, not creating and using a new one.
Thanks!
It is not possible. Each class can be mapped only once per mapping set (per context in common cases). Why? Because the access point to database is a DbSet (or ObjectSet in ObjectContext API) and it is simply created this way:
var set = dbContext.Set<Statistics>();
How should EF know which mapping of Statistics class should be used? It must know which mapping to use to query correct table and to save changes to correct table. You can probably argue that it could be defined as parameter but that would expose mapping details outside to upper layer - that is undesirable.
Edit:
If your application logic never needs access to more than one customer's statistics you can create mapping per customer dynamically. You need:
Create instance of DbModelBuilder and define mapping (or fill Configurations) - in this step you will provide the name of the table for current customer
Call Build method to get DbModel instance
Call Compile on DbModel instance to get DbCompiledModel instance
Cache compiled model somewhere. Model compilation is expensive operation and you need to do it only once per each customer (and per each application restart).
Pass compiled model to DbContext constructor and use that context instance to access data only for that customer
If you need to simultaneously access data for multiple customers you must do it through SQL.
I develop a simple MVC3 CRUD application - simple controllers / views, which uses WCF service for CRUD data access.
The WCF uses EF4.1 with DbContext, and simple CRUD-style methods: ListEntities, GetEntity(ID), AddEntity (entity), DeleteEntity(ID)
If I develop the MVC application directly with EF, code first, I can annotate properties in the entity classes with validation attributes, and the MVC application will automatically recognize validation errors and report them in the UI when I try to save and a validation error occurs (e.g. a required field is not set).
But in my application I don't use this approach and I face two problems:
My entities in the WCF are generated from the EDMX, which in turn was also generated from the database. So I cannot actually add to them any data validation annotation attributes, because they'll vanish as soon as the entities will be regenerated from the EDMX. Is there any solution to this?
Since my client (MVC app) does not share the data contract classes with WCF (for clear separation), but instead it is generated form service reference, even if I find a way to add data annotation attributes to server-side data contract classes, will they be recognized and recreated when the data contract proxy class is created on client side?
So how could I made the MVC application to use client side validation and error message reporting for validation failures when binding to entities exposed by WCF service as data contracts?
One idea I have is, on client side, to create derived classes for all entities exposed as data contracts, and apply annotation attributes to them to desired properties. But this doesn't looks like a good solution to me, because with this I create a logic "coupling" between UI client and the WCF service / data layer (forcing UI to know about data more than it should do - by putting BL logic in client).
Can anyone give me some suggestions on how to handle those this situation?
Thanks
1: Yes you can add validation using the System.ComponentModel.DataAnnotations.MetaDataType.
I answered this question at MVC Partial Model Updates
2a: What you can do is create a seperate Class Library Assembly that contains all the interfaces (with or without additional MetaDataTypes) and use that on both the WCF service and the MVC application. After you add the reference to your MVC application, when adding the WCF Service reference, you can match the WCF Service DataContacts directly to the interfaces in the Assembly. One Caveat is that both the WCF service and MVC application are dependant on the Assembly (some might consider this tightly coupled) but this should be ok because you are only tightly coupling at the interface level, and whether or not you choose to allow VS to recreate it's own interfaces/classes or reuse what you already created in the Assembly it boils down to the same thing in my opinion.
2b: If you decide not to use a Class Library, I'm pretty sure that the service reference classes are partial, and you can simply create another .cs file with partial classes and add the interfaces as I described in part 1 to the partial classes.
Update
I am currently using Entity Framework to access my database. Entity Framework, like WCF References, classes are Auto-Generated classes will look something similar to:
[EdmEntityTypeAttribute(NamespaceName="MyNameSpace", Name="Info ")]
[Serializable()]
[DataContractAttribute(IsReference=true)]
public partial class Info : EntityObject
{
public static Info CreateInfo (global::System.Int32 id)
{
Info info= new Info ();
info.Id = id;
return info;
}
public string Name { get; set; }
public string FavoriteColor { get; set; }
// etc etc
}
In a separate file with the same namespace as the previous partial class, I have created:
[SomeAttribute1]
[AnotherAttribute2]
public partial class Info: IInfo
{
}
So now my auto-generated class is not only based on an Interface I created IInfo so the actual methods are not exposed (because my datatier in MVC returns interfaces), but it also has Attributes (for Data Annotations or whatever).
What I would suggest is instead of putting your data annotations directly on your WCF Service reference class is to use the MetedataType DataAnnotations. This allows you to separate the actual data object with the data annotations validations. Especially helpful if you want to use the same data class with different validations based on whatever (maybe administrators don't have to have a valid favorite color).
For example:
public interface NormalUser
{
[Required]
string Name { get; set; }
[Required]
string FavoriteColor { get; set; }
}
public interface AdminUser
{
[Required]
string Name { get; set; }
string FavoriteColor { get; set; }
}
[MetadataType(typeof(INormalUser))
public class NormalUserInfo : Info { }
[MetadataType(typeof(IAdminUser))
public class AdminUserInfo : Info { }
In this example we have two different classes NormaUserInfo and AdminUserInfo which both have different validations. Each of them have inherited from Info so they are valid models that can be passed into the WCF Service.
Out of my mind, as I can't test it right now...
Let's say your autogenerated code is like this:
public partial class Employee
{
//some code here
}
You can add a new Employee class, also partial, and this one won't be autogenerated
[you can annotate here]
public partial class Employee
{
//somecode here
}
try it
As for the validation, you could use: http://fluentvalidation.codeplex.com/
I've made a custom model, and I want to mock it. I'm fairly new to MVC, and very new to unit testing. Most approaches I've seen create an interface for the class and then make a mock that implements the same interface. However I can't seem to get this to work when actually passing the interface into the View. Cue "simplified" example:
Model-
public interface IContact
{
void SendEmail(NameValueCollection httpRequestVars);
}
public abstract class Contact : IContact
{
//some shared properties...
public string Name { get; set; }
public void SendEmail(NameValueCollection httpRequestVars = null)
{
//construct email...
}
}
public class Enquiry : Contact
{
//some extra properties...
}
View-
<%# Page Language="C#" Inherits="System.Web.Mvc.ViewPage<project.Models.IContact>" %>
<!-- other html... -->
<td><%= Html.TextBoxFor(model => ((Enquiry)model).Name)%></td>
Controller-
[HttpPost]
public ActionResult Index(IContact enquiry)
{
if (!ModelState.IsValid)
return View(enquiry);
enquiry.SendEmail(Request.ServerVariables);
return View("Sent", enquiry);
}
Unit Testing-
[Test]
public void Index_HttpPostInvalidModel_ReturnsDefaultView()
{
Enquiry enquiry = new Enquiry();
_controller.ModelState.AddModelError("", "dummy value");
ViewResult result = (ViewResult)_controller.Index(enquiry);
Assert.IsNullOrEmpty(result.ViewName);
}
[Test]
public void Index_HttpPostValidModel_CallsSendEmail()
{
MockContact mock = new MockContact();
ViewResult result = (ViewResult)_controller.Index(mock);
Assert.IsTrue(mock.EmailSent);
}
public class MockContact : IContact
{
public bool EmailSent = false;
void SendEmail(NameValueCollection httpRequestVars)
{
EmailSent = true;
}
}
Upon a HttpPost I get a "Cannot create an instance of an interface" exception. I seems that I can't have my cake (passing a model) and eat it (pass mock for unit testing). Maybe there's a better approach to unit testing models bound to views?
thanks,
Med
I'm going to throw it out there, if you need to mock your models you're doing it wrong. Your models should be dumb property bags.
There is absolutely no reason that your model should have a SendEmail method. That is functionality that should be invoked from a controller calling to an EmailService.
Responding to your question:
After years of working with Separation of Concern (SOC) patterns like MVC, MVP, MVVM and seeing articles from people brighter than me (I wish I could find the one I'm thinking off about this but maybe I read it in a magazine). You will eventually conclude in an enterprise application you will end up with 3 distinct sets of model objects.
Previously I was a very big fan of doing Domain Driven Design (DDD) using a single set of business entities that were both plain old c# objects (POCO) and Persistent Ignorant (PI). Having domain models that are POCO/PI leaves you with a clean slate of objects where there is no code related to accessing the object storage or having other attributes that have schematic meaning for only 1 area of the code.
While this works, and can work fairly well for a period of time, there is eventually a tipping point where the complexity of expressing the relationship between View, Domain Model, and Physical Storage Model becomes too complex to express correctly with 1 set of entities.
To solve the impedance mismatches of View, Domain and Storage you really need 3 sets of models. Your ViewModels will exactly match your views binding to facilitate it to be easy to work with the UI. So this will frequently have things such as adding a List to populate drop downs with values that are valid for your edit view/action.
In the middle is the Domain Entities, these are the entities that you should validate against your business rules. So you will map to/from them on both sides to/from the view and to/from the storage layer. In these entities is where you could attach your code to do validation. I personally am not a fan of using attributes and coupling validation logic into your domain entities. It does make alot of sense to couple validation attributes into your ViewModels to take advantage of the built in MVC client side validation functionality.
For validation I would recommend using a library like FluentValidation (or your own custom one, they're not hard to write) that lets you separate your business rules from your objects. Although with new features with MVC3 you can do remote validation severside and have it display client side, this is an option to handle true business validation.
Finally you have your storage models. As I said previously I was very zealous on having PI objects being able to be reused through all layers so depending on how you setup your durable storage you might be able to directly use your domain objects. But if you take advantage of tools like Linq2Sql, EntityFramework (EF) etc you will most likely have auto generated models with code for interacting with the data provider so you will want to map your domain objects to your persistence objects.
So wrap all of this up this would be a standard logic flow in MVC actions
User goes to edit product page
EF queries the database to get the existing product information, inside the repository layer the EF data objects are mapped to the Business Entities (BE) so all the data layer methods return BEs and have no external coupling to the EF data objects. (So if you ever change your data provider you don't have to alter a single line of code except for the internal implementation)
The controller gets the Product BE and maps it to a Product ViewModel (VM) and adds collections for the different options that can be set for drop down lists
Return View(theview, ProductVM)
User edits the product and submits the form
Client side validation is passed (useful for date validation / number validation instead of having to submit the form for feedback)
The ProductVM gets mapped back to ProductBE at this point you would validate the business rules along the lines ValidationFactory.Validate(ProductBE), if it's invalid return messages back to view and cancel edit, otherwise continue
You pass the ProductBE into your repository model, inside the internal implementation of the data layer you map the ProductBE to the Product Data Entity for EF and update the database.
2016 edit: removed usages of Interface as separation of concerns and interfaces are entirely orthogonal.
Your issue is here:
public ActionResult Index(IContact enquiry)
MVC in the background has to create a concrete type to pass to the method when calling it. In this method's case, MVC needs to create a type which implements IContract.
Which type? I dunno. Neither does MVC.
Instead of using interfaces in order to be able to mock your models, use normal classes that have protected methods which you can override in mocks.
public class Contact
{
//some shared properties...
public string Name { get; set; }
public virtual void SendEmail(NameValueCollection httpRequestVars = null)
{
//construct email...
}
}
public class MockContact
{
//some shared properties...
public string Name { get; set; }
public bool EmailSent {get;private set;}
public override void SendEmail(NameValueCollection vars = null)
{
EmailSent = true;
}
}
and
public ActionResult Index(Contact enquiry)
It is possible to use interfaces.
See: http://mvcunity.codeplex.com/