Referencing my Models in DAL - data-access-layer

Happy New Year everyone. Ok, i'm trying to create a 3 tier application and i have my references in the following order UI -> BLL -> DAL. The question is. The problem i'm having is with the Dbset. Because i have no reference to my models within my DAL, the dbset fails.
namespace MyApp.DAL
{
public class MyAppDb : DbContext
{
public MyAppDb() : base("name=MyAppDBstring")
{ }
public DbSet<SomeModel> SomeModels { get; set; }
}
}
How do i get this to work if it cant find my SomeModel class in my BLL? Any help would be greatly appreciated.

In this case you would need to add a reference to your BLL project in your DAL project. Right click References>Add Reference and then the Solution tab tick your BLL project.
From this you will then be able to put a using statement on the top of the class above something along the lines of:
using MyApp.BLL;

Related

VS 2013 Controller Scaffolding Fails for the ApplicationUser Model (Multiple object sets per type are not supported)

In a VS 2013 RTM, MVC 5 project with EF 6, I tried to scaffold a controller based on the ApplicationUser (default with individual accounts authentication). Both ApplicationUser and IdentityUser are mapped to a Users table.
The wizard opens the context file for editing and tries to add a new db set for ApplicationUser (ApplicationUsers) and then fails with this error:
Unable to retrieve metadata for ApplicationUser. Multiple object sets per type are not supported. The object sets ApplicationUsers and Users can both contain instances of type ApplicationUser
The solution does not have any reference to, or instance of ApplicationUsers.
Is this a known issue? Can the scaffolding be run using command line with options (from PMC)?
Note: scaffolding also adds an extra db set to the context class if I specify a model that references ApplicationUser (the app works if I remove it and fix references in the generate controller).
Wow. I'm really surprise that no one actually got to the root of this, and instead, are just recommending workarounds.
IdentityDbContext already contains a property:
`public virtual IDbSet<TUser> Users { get; set; }
When you subclass IdentityDbContext to create your own application-specific context, you must specify what class satisfies the TUser generic. The default is:
public ApplicationDbContext : IdentityDbContext<ApplicationUser>
Which then means that you functionally have a property already via inheritance in the form of:
public IDbSet<ApplicationUser> Users { get; set; }
If you then add another property to your application-specific context such as:
public DbSet<ApplicationUser> ApplicationUsers { get; set; }
You now have the same entity tracked by two DbSets, and you get that error. The solution? Simply don't add your own DbSet for ApplicationUser. There's no need to rename or override anything.
Short-Version: Rename your ApplicationUser class to User.
I've been running into this problem for about a month with absolutely no luck...until now!
Initially, I thought it was a preview issue, but after persisting into the RTM along with the latest libraries, I became incredibly annoyed, since this problem persisted into Migrations too.
However, IdentityDbContext, according to the error message, seems to be creating two DbSets: ApplicationUsers and Users. We only want Users when looking at the source code:
public class IdentityDbContext<TUser> : DbContext where TUser : Microsoft.AspNet.Identity.EntityFramework.IdentityUser
{
...
public virtual IDbSet<TUser> Users { get; set; }
...
}
From this, we (and the scaffolding engine, and the migrations engine) should only see "Users", not "ApplicationUsers".
To rectify this situation, you will need to adjust your application class to account for this rather strange error. Simply rename your ApplicationUser class to User:
using Microsoft.AspNet.Identity.EntityFramework
...
public class ApplicationUser : IdentityUser
{
Your Stuff
}
To:
using Microsoft.AspNet.Identity.EntityFramework
...
public class User: IdentityUser
{
Your Stuff
}
Attempt to Scaffold again. If you receive another error along the lines of the class cannot be found, save your project, close VS2013, re-open VS2013, load the project, re-build the project, and finally attempt to scaffold. The IdentityDBContext should no longer be creating a dummy "ApplicationUsers" DBSet object causing both Entity Migrations and Scaffolding to issue these errors.
Hope this helps!
P.S. Any mapping done ought not to affect this problem, so you should be able to still map to the same table if you wish to.
EDIT:
If you receive further problems, undo the rename. I ran into some problems (more scaffolding and query errors), and after I went back to ApplicationUser, those problems disappeared and the problem above did not re-occur. Just a heads up.
Read the above problems en solutions.
My error text was:
Multiple object sets per type are not supported. The object sets
'ApplicationUsers' and 'Users' can both contain instances of type
'DataLayerIdentity.Models.ApplicationUser'
I suspect the error was created when I was playing around and scaffolded the model: ApplicationUser in a new controller.
Solved it by removing the below from : ApplicationDbContext.cs
public System.Data.Entity.DbSet<DataLayerIdentity.Models.ApplicationUser> ApplicationUsers
{
get;
set;
}
No Other changes where made to solve the problem. I hope this helps someone.
When you use scaffolding to generate control, vs will auto insert 1 line to your db context
public System.Data.Entity.DbSet<...API.Models.ApplicationUser> ApplicationUsers { get; set; }
Just delete that line, and in your controller. change
db.ApplicationUsers to db.Users
Here is the simplest solution. When you add/scaffold a view (list) based on ApplicationUser as the model, VS2013 ADDS the following to the IdentityModels.vb or .cs file.:
Public Property ApplicationUsers As System.Data.Entity.DbSet(Of ApplicationUser)
Just remove this property and the problem goes away.
If you are trying to create an ApplicationUsersController please follow these steps.
Delete this line from IdentityModels.cs
public System.Data.Entity.DbSet<Project.Models.ApplicationUser> ApplicationUsers { get; set; }
Build the project
control + shift + b
Generate the controller
Right click on the 'Controllers' folder.
Add > Controller
MVC Controller with views, using Entity Framework
Model Class: ApplicationUser
Add
Go back to IdentityModels.cs and delete this line AGAIN
public System.Data.Entity.DbSet<Project.Models.ApplicationUser> ApplicationUsers { get; set; }
Build the project
control + shift + b
Change the database calls to from ApplicationUsers to Users in ApplicationUsersController.cs
control + f to bring up 'Find and Replace'
Click 'Replace in files'
Find what: db.ApplicationUsers
Replace with: db.Users
Replace All
Press play and cross fingers :)
What you can also do:
Create an empty controller, and add the code for the DataContext yourself
protected ApplicationDbContext db { get; private set; }
public HomeController() : this(new ApplicationDbContext())
{
}
public HomeController(ApplicationDbContext db)
{
this.db = db;
}
Then create your methods like Index, Create and so on, and create the views with right-clicking and "Add view..." for each.
Scaffold your views with the list, create, whatever template that is appropriate and choose the ApplicationUser as an model.
Important: Delete the entry in "Data context class", or you will get a similar error again. But if you leave the "Data context class" empty, the scaffolding of the view will work out fine.
I fixed problem by removing DbSet from context and then changing references in controller from ApplicationUsers to Users. It worked - but now i see no point in scaffolding users.
To much things has to by maintained on top level and it just does not work right. Now i know that view models and repository are the way I want to go.

Problems with EF-Agnostic design consumed by WCF service.

I am trying to set up EF to work on WCF and keeping the domain class models EF Agnostic.
The code is organized into 3 projects. (I am taking a stab a DDD - I am very new to it but am looking forward t learning more)
Project: QA - Domain Layer. Contains the DataContract models/entities.
References
QA.Data
Project: QA.Data - Data Layer. Contains the context and EDMX (code generation stragtegy = "none")
References
Entity Framework/System.Data.Entity
Project: QA.Repository - Data Access/Repository. Contains the repository classes
References
QA [Domain Layer]
QA.Data [Data Layer]
Entity Frame/System.DataEntity
My understanding is that the domain layer can reference the data layer but the data layer should never reference the domain. The problem that this presents is that my Domain Models/Classes are defined in the Domain layer but the Context which creates and returns them is in the Data layer. In order for my context to know to return a "Widget" object it would need a reference to the Domain layer which defined the "Widget"
My (failed) solution : My solution was to create interfaces for each Domain Model and place them in the data layer. The context would return ... IdbSet ... These interfaces would, in turn, be implemented by the Domain Models, therefore keeping my data layer from directly needing to reference my domain (which causes illegal circular references anyway). The domain models were originally contructed using "ADO.NET DbContext Generator w/WCF Support" T4 templates. This process resulted in the inclusion of the [KnownType(typeof(IWidgetPiece))] at the beginning of of the widget class defin ition. (A Widget has a navigation property ... ICollection ...)
The problem appears when I attempt to access the service, I get the following error
'QA.Data.IWidgetPiece' cannot be added to list of known types since
another type 'System.Object' with the same data contract name
'http://www.w3.org/2001/XMLSchema:anyType' is already present. If
there are different collections of a particular type - for example,
List and Test[], they cannot both be added as known types.
Consider specifying only one of these types for addition to the known
types list.
I can change these to the concrete implementations ... [KnownType(typeof(WidgetPiece))] ... but I continue to get this error because the navigation property they are referring to is still returning an IWidgetPiece interface type which it MUST do in order to satify the interface implementation.
I am trying to figure out how to keep things appropriately divided and still have the context returning what it should. the context returning Interfaces still doesn't "sit" right with me for this and other reasons but I cannot think of another way to do this, and even this is presenting the aforementioned issue. HELP!
Some code to hopefully clarify my previous ramblings ...
namespace QA.Data
{
public interface IWidgetPiece
{
String ID { get; set; }
}
public interface IWidget
{
String ID { get; set; }
ICollection<IWidgetPiece> Pieces;
}
public partial class WidgetEntities : DbContext
{
IDbSet<IWidget> Widgets { get; set; }
IDbSet<IWidgetPiece> WidgetPieces { get; set; }
}
}
namespace QA
{
[KnownType(typeof(IWidgetPiece))]
// [KnownType(typeof(WidgetPiece))]
[DataContract(IsReference = true)]
public partial class Widget : QA.Data.IWidget
{
[DataMember]
public String ID { get; set; }
[DataMember]
public virtual ICollection<IWidgetPiece> Pieces { get; set; }
}
[DataContract(IsReference = true)]
public partial class WidgetPiece : QA.Data.IWidgetPiece
{
[DataMember]
public string ID { get; set; }
}
}
namespace QA.Repository
{
public class WidgetRepository
{
public List<Widget> GetWidgetbyID(String sId)
{
WidgetEntities context = new WidgetEntities();
List<IWidget> objs = context.Widgets.Where(b => b.ID == "78").ToList();
List<Widget> widgetList = new List<Widget>();
foreach (var iwidget in widgetList)
widgetList((Widget)iwidget);
return widgetList;
}
}
}
Do you really want / need two separate models i.e. your data access layer model (edmx) and your "real" domain model? The whole point of an ORM framework like EF is so you can map your domain model to your database tables, using mappings between the physical (database) conceptual model.
Since EF4.1, you can construct your domain model and then in your data access layer map that to your database directly using a fluent API. You can also elect to reverse-engineer your POCO domain model from a database if you want to quickly get up an running.
It just seems a bit of unnecessary complexity to create an entire EF class model, only to then have to map it again into another class model (which will most likely be fairly close to the EF-generated one).

Linq to SQL - Attribute based mapping - cannot instantiate new object with no arguments

I want to extend Linq's DataContext class to implement the ORM. Currently my model looks like this:
public class Trial : DataContext
{
public Trial(string connectionString) : base(connectionString) { }
[Column(DbType = "System.Guid", IsPrimaryKey = true, IsDbGenerated = true, CanBeNull = false)]
public Guid TrialID { get; set; }
//...
}
However when I try to instantiate a new Trial object to insert it into the database I get an error complaining that Trial does not have a constructor that takes 0 arguments. When I try to create such a constructor, VS complains that DataContext does not have a constructor that takes 0 arguments.
Am I missing something here? How do I seperate the data context from the model definition?
(First time using Linq!)
Thanks in advance,
Max.
Your data context that represents the database view should inherit from DataContext. It should expose Tables where T is the entities (rows) that you want to add. Try generating a model from the database using the designer or SQLMetal and take a closer look at the generated code to see what's going on.

In WCF how do you put a datacontract on a class that has already been defined elsewhere?

So I have some class in a business logic .dll. It is not wrapped in a datacontract, I would like to expose it to anything calling the service by doing so in the Service and IService classes (for example). But the only examples I have seen have been to expose classes that are defined in the service, I do not wish to do this and I do not wish to use [Datacontract] in my business logic layer if that makes sense?
Ask if any clarification is required. Help is as always most appreciated.
Thanks :)
edit: I am slightly confused by many of these solutions, what I would like to do is provide the caller of the service a range of classes to instance and then pass back to the service through a method. So:
public Class ServiceConsumer{
addPerson(){
theService.addPerson(new theService.Person("Thomas", 22, "Male");
}
}
Does that make sense? That's a bit pseudo-codish as I can't remember the consumer side of WCF calls off the top of my head. All the solutions seem to require either knowledge of what classes are available or the classes mashed together in one class?
The only other solution I can see so far is to have a method for every class, but let me tell you there will be potentially a hundred classes!
Many thanks.
For starters, don't annotate the business object with [DataContract]. It's considered bad practice.
About 35 minutes into this video Miguel talks about data contracts.
What you need to use is a Data Transfer Object. It will make sure that there is proper separation between your Business Layer and the Service Layer. Also check this link.
While you should layer it properly, there are some cases where you dont really need the seperation of UI, Service, and Business Logic. Generally this happens when you are developing a smaller project, and its really not going to grow.
If you choose you still want to do this, see the example below. You are basically going to wrap your types in a Proxy like "RequestContract" In my case my BL types would be MyType and ByMyType. Those two classes are not annotated and they are brought in using DataContracts defined in the service.
public class ExampleService : IExampleService
{
public ExampleService() { }
public GetMyTypeResponseContract GetMyType(GetMyTypeRequestContract theType)
{
return new GetMyTypeResponseContract()
{
MyType = new MyType()
{
Response = theType.ByMyType.Request
}
};
}
}
[DataContract]
public class GetMyTypeRequestContract
{
[DataMember]
public ByMyType ByMyType { get; set; }
public GetMyTypeRequestContract() { }
}
[DataContract]
public class GetMyTypeResponseContract
{
[DataMember]
public MyType MyType { get; set; }
public GetMyTypeResponseContract() { }
}
Have you considered using POCO - http://msdn.microsoft.com/en-us/library/ee705457.aspx
From a technology point of view, you can use a surrogate.

AutoMapping Custom Collections with FluentNHibernate

I am retrofitting a very large application to use NHibernate as it's data access strategy. Everything is going well with AutoMapping. Luckily when the domain layer was built, we used a code generator. The main issue that I am running into now is that every collection is hidden behind a custom class that derives from List<>. For example
public class League
{
public OwnerList owners {get;set;}
}
public class OwnerList : AppList<Owner> { }
public class AppList<T> : List<T> { }
What kind of Convention do I have to write to get this done?
I don't think you're going to be able to achieve this with a convention. You will have to create an auto mapping override and then do the following:
mapping.HasMany(l => a.owners).CollectionType<OwnerList>();