MVC Scaffolding Issue - asp.net-mvc-3

When I try to Scaffold My Controller, the page throws following error
"Unable to retrieve metadata for 'Entity.Observation'. No parameterless constructor defined for this object."
Can you help me this?
Here is the code:
public class Observation
{
public Observation() { }
public virtual int Id { get; set; }
public virtual DateTime Date { get; set; }
public virtual User Teacher { get; set; }
public virtual User Observer { get; set; }
public virtual AcademicYear AcademicYear { get; set; }
}
Entities is in other project, Context is in different project and Controllers and Views are in same project
I am using Entity Framework Code First model

I had the exactly same problem, the error stated that a default (parameterless) constructor was missing from my model. In my case the error was misleading - my model did in fact contain a default constructor but my DataContext did not. I added a default constructor to my DataContext - problem solved!
public class ReportEntities : DbContext
{
public ReportEntities():base()
{
}
public ReportEntities(string connection)
: base(connection)
{
}
...
}

I had the same problem. Here's how I fixed -
First, I added another constructor with no parameter to the context
class (not the model class).
After that I had to rebuild the project. Really important because the tooling reads the meta data (i burned 10 miuntes before I realized I had to do this).
Once I did those two things, I was able to add the controller and views with no problem.

If you have you EF models in a separate project you can try right clicking the edmx file and "Add Code Generation Items" and choose "DbContext Generator". This is available only if you have EF 4.1 (easiest way to install is to use NuGet). See if that helps. Every time I make a change to my model project I generally make sure i build that project before I start working on the other projects.

If you in fact did add the parameterless constructor and you're still getting the error, it sounds like your build isn't updating. So try this:
First off all, add a parameterless constructor: public void Observation(){}, or have no constructors at all.
However, scaffolding is done using metadata; reflection. Before you retry you'll have to rebuild the project with the model in. In this case: Observation make sure there are no build errors.
Since you said the entity was in another project, make sure the reference is correct. For example: click the reference to the entities dll, and make sure the path is correct. Also, make sure Copy Local is on false. If its on true; the dll only gets "copied local" one time. You're probably working with an old version.
If it still fails after that, try to delete the entities dll first, and rebuild, so you're 100% sure you're working with a new version.

Related

Add attributes to Entity Framework database first generated classes

I am using Entity Framework 4.1 and generating my classes using the database first approach. I have a an EDMX file in my solution.
I am trying to add attributes to my classes using the MetadataTypeAttribute approach which seems to be the recommended way of doing this outside of editing the T4 template, however, I cannot seem to get it to work because I keep getting this compile error:
'Patient' is an ambiguous reference between 'PatientManagementSystem.Patient' and 'PatientManagementSystem.Models.Patient'
Here is the code I am using:
[MetadataTypeAttribute(typeof(PatientMetadata))]
public partial class Patient
{
}
public class PatientMetadata
{
[Required]
public string LastName {get; set;}
}
Is this error happening because I don't actually have classes for this because I am doing Database first and everything in the EDMX?
Thanks!
Flea
Make sure both are in the same namespace. Since it's a partial class, the class you are modifying must also be in the same namespace or it isn't the same class.

MVC3 using EF4.3 and Dependancy Injection issues

I have recently been learning MVC3 using Entity Framework 4.3 and Dependancy Injection so I can implement unit tests at a later date. I am now trying to implement some functions I have seen in various examples however I have hit a few issues that seem to stem from my use of dependancy injection and therefore I would like someone to point out where I am going wrong.
My first question is pretty simple; In most MVC3 examples I have seen, the access to the database is done in controllers, but when using dependancy injection I seem to need to refactor this code out to the implemented repository. Is this normal and correct?
My second more indepth issue is dealing with this simple example:
I have this method in my repository class which is pretty much copied from an online example (here). However I get an error regarding the Include part, and the intellisense does say that the variable needs to be a string. I have tried the original code from the link I mentioned earlier and that works fine, the only major difference between the project is that I am using dependancy injection.
public ExampleUser GetStruContractUser(int id)
{
ExampleUser user = context.ExampleUsers
.Include(i => i.ExampleRoles)
.Where(i => i.UserID == id)
.Single();
return user;
}
Changing the Include parameter to the following works fine.
public ExampleUser GetStruContractUser(int id)
{
ExampleUser user = context.ExampleUsers
.Include("ExampleRoles")
.Where(i => i.UserID == id)
.Single();
return user;
}
For reference this is my DbContext class that I am using:
public class EFDbContext : DbContext
{
public DbSet<ExampleUser> ExampleUsers { get; set; }
public DbSet<ExampleRole> ExampleRoles { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<ExampleUser>().ToTable("User", "MySchema");
modelBuilder.Entity<ExampleRole>().ToTable("Role", "MySchema");
modelBuilder.Entity<ExampleUser>()
.HasMany(m => m.ExampleRoles)
.WithMany(t => t.ExampleUsers)
.Map(a =>
{
a.MapLeftKey("UserID"); // your PK column name in user table
a.MapRightKey("RoleID"); // your PK column name in role table
a.ToTable("UserRole", "MySchema"); // your join table name
});
}
}
Is this an issue due to my use of dependancy injection or is there something else going on that I am misunderstanding?
If you need more information, please ask and I will try and provide it.
Thanks very much.
Question 1:
Using DI doesn't force you to use a repository pattern, in fact they are not related. It's just a nice way to avoid tightly coupling your controller classes to the database context class, and being able to thus test those classes more easily. Repository gives you the ability to hide the implementation details of how you're accessing the DB, and allows you to switch ORM:s if that were to happen (and it never ever does). Repository relies on you to provide interfaces for your DbContext, and so does using DI.
What you want to do is use your DB through an interface nevertheless, and seeing as you're using DI, you could just inject the reference to the DbContext class in the constructor of your controllers, and let the DI controller do the work for you.
The reason it is preferable to pass in an interface that defines the repository to the Controller over passing an interface that defines your DbContext, is because making an interface of the latter can easily become overly complex, whereas sticking to a repository is much simpler. For simplicity though, I'd start with just using DbContext directly, and then expanding from there.
Question 2:
Include needs to contain the name of the table as a string. So your latter use of Include is correct, and the former isn't.
If I remember correctly, you can do this tho: ".Include(i => i.ExampleRoles.Name)" to achieve the same thing.
Yes, extracting your database layer (repositories / context) and then injecting it into your business layer (controllers) is very normal and a good way future proof your application. What if you ever wanted to change your database ORM from Entity Framework to something else? Having it tightly coupled with your controllers would create a huge headache.
Your second issue, with include, is unrelated to the dependancy injection.
Include on a dbset using lambdas an extension in System.Data.Entity. You'll need to include that reference if you want to use it.

Cannot Create Controller with EF Generated DBContext Classes using Partial Classes

I have an interface defined as:
public interface ICMDBContext
{
DBSet<Building> {get;}
DBSet<Room> {get;}
more DBSet methods...
string Save()
}
I have the DBContext generated class named CMDB_DataModelContainer.
I have a partial class CMDB_DataModelContainer which implements ICMDBContext which looks like this (And yes, both are in the same namespace):
public partial class CMDB_DataModelContainer : ICMDBContext
{
string Save() { implemenation... }
}
Everything compiles all fine and dandy, but when I try to create a controller and use CMDB_ModelConatiner as the context class (creating a Strongly-typed controller) I get the error
There was an error generating 'CMDB.Domain.Models.CMDB_DataModelContainer'. Try rebuilding your project.
I removed the partial class and was able to create the controller. Any ideas why this would happen?
To add, the DBContext classes are in a separate project.
The fact it is in a separate project doesn't matter. I created a test project with DBcontext class and the MVC3 app in same project and still a no go.
I suppose a question to ask is if anyone has actually setup a repository when using Model first approach. I am finding myself running into problem after problem trying to apply this pattern when using model first.
If you want to recreate the issue, just make an MVC 3 (or 4, I used 3). This is what I did for a test to recreate it myself.
Add a new ADO.Net Entity Data Model.
Create two entities: Taco and Filling
Add a "name" scalar property to each.
Add association m <---> m
Create a new folder named "Partial" in the models folder.
Add a new class - the class should be named the same as the Context class (if you left default names it should be Model1Container) and in the same namespace.
e.g.
public partial class Model1Container
{
}
- Add a new controller "TacoController" as strongly typed against, you guessed it, Taco, and using the Model1Container as the context class. Voila, reproduced. Yes, I like tacos.
As you have probably discovered, removing(/renaming) the partial class, creating the controller and then reinstating your partial class seems to be an adequate workaround. As for why:
One of the times I tried I noticed something strange: a new declaration had appeared in the partial class file I'd created:
public DbSet<Taco> Taco { get; set; }
I can only speculate that VS is getting confused by the partial class files - it finds the partial class file you created, doesn't see the DBSet declared, tries to add it and then gets in a tizzy because that's too many tacos.
Chris

MVC3 - EF4: One DbContext for all Repositories and ViewModels - UnitOfWork?

I'm totally stuck.
I've got two Controller: "Customer" and "Address". Both have the fields CustomerRepository and AddressRepository.
There are two ViewModels: CustomerViewModel and AddressViewModel. They also have the fields CustomerRepository and AddressRepository. (And also a parameterless constructor since they are parameters within the edit and create methods)
The Repositories themselves have a DbContext object from my Entities.
Now I'm running into one problem after another. I think I should have only ONE DbContext to share with all of my classes (Repositories AND ViewModels). And I think UnitOfWork is the solution. But I have no clue how to use that.
I currently tried to create a DbContext within the controllers constructor and pass it to every single object requiring it. But even that doesn't work.
If code is necessary, I will post it.
Couple of things to know:
1. Unit of Work
Unit of Work is not necessarily some kind of implementation for IUnitOfWork. It is just a pattern that might be applied in many ways. First, and foremost - you should understand what is it for before actually using it and overcomplicate things around. Moreover, EF Code-First DbContext API's DbContext is a kind of Unit of Work pattern. Your IDbSet<>s are your repositories. Don't try to abstract from your ORM, start with simplest possible thing.
2. DbContext injection
For the beginning, just inject the DbContext to your Controller with constructor injection. Don't forget to setup the IoC container of choice and wire up the MVC's DependencyResolver. Your controller could be look like (example also contains AutoMapper usage example, see next point about ViewModels for that):
public CustomerController : Controller
{
public CustomerController(MyDbContext data, IMappingEngine mapper)
{
Data = data;
Mapper = mapper;
}
public MyDbContext Data { get; set; }
public IMappingEngine Mapper { get; set; }
// Other controller code
}
3. View Models
This, again, is a pattern that is so easily implementable - just have your CustomerViewModel and use AutoMapper to easily transform your Customer to CustomerViewModel so that you can do it like this:
public ActionResult Details(int id)
{
var customer = Data.Customers.FirstOrDefault(c => c.Id == id);
if (customer == null)
return new HttpNotFoundResult();
return View(Mapper.Map<CustomerViewModel>(customer));
}
You can interrogate the AutoMapper's website on how to wire it up and make it running.
Notice that you don't get the ViewModel from DbContext directly. You obtain an "entity" instead which then transformed to appropriate View Model.
Hope this helps!
Your ViewModels should not have references to the DbContext or repositories. ViewModels should be largely stupid. It is the job of the controller (or a service called by the controller) to populate the ViewModels with the data the View needs.
Unit Of work is a good pattern, and one you should use.. but the patern is not a fix for your problem. Your problem is that you are making your view have too much knowledge of your data model.
I currently do the following:
One injected IUnitOfWork using unity to inject into my controllers.
IUnitOfWork implements IContext.
IContext contains IDbSet Customers and IDbSet
The concrete implementation of IContext implements DbContext.
My controllers reference a service, the service uses the IUnitOfWork.
If you use a repository, then simply use a single IContext injected into your controller (or IUnitOfWork which is fairly easy to add on top)
This way I have one context per lifetime of the request and then it's disposed. If you want more code let me know I'll see what I can post up here.

ADO.NET Entities - Model-first data annotations

I'm using the approach explained here:-
http://blogs.msdn.com/b/adonet/archive/2010/12/06/ef-feature-ctp5-code-first-walkthrough.aspx
I'd like to use the surface designer to develop my model, then use partial classes to include data annotations for validation. However, if I use a partial class and then attempt to reference an existing property the compiler complains that the property already exists.
How do I get over this?
e.g.
public partial class Product
{
[Required(ErrorMessage="Name is required")]
public string Name { get; set; }
}
The compiler says "Name is already defined".
I just ran across the same problem on how to annotate an entity class that is generated from the Entity Data Model and I found the answer on another stackoverflow thread:
Using System.ComponentModel.DataAnnotations with Entity Framework 4.0

Resources