Should we add Entity Framework dll to all layers - entity-framework

I am writing a test app using EF code first. I have distributed code among different layers. I thought I would have to install the entity framework package to the data access layer only but what I ended up with is installing the package (adding dlls) to all the layers namely UI, BLL, Models, DAL. Is this okay or I am doing something wrong. Below is sample code to give you an idea of what I am trying to do
Model Layer
This layer is reference in all other layers/projects
namespace Model
{
Public class Sample
{
[ForeignKey("Sample2Id")]
...
}
}
In this layer I had to use Entity Framework dlls because of Data Annotation like [ForeignKey..
DAL
namespace DAL
{
public class SampleContext:DbContext
{
...
}
}
In DAL I only have the context class and migrations
BLL
namespace BLL
{
public class SampleBLL
{
public List<Sample> GetAll()
{
retrn new SampleContext().Samples().ToList()
}
}
}
If I uninstall EF for BLL I get the following error
The type System.Data.Entity.DbContext is defined in an assembly that is not referenced.
UI
namespace UI
{
public class UIHelper
{
public List<Sample> GetSamples()
{
return new SampleBLL().GetAll();
}
}
}
If I uninstall the EF package from UI I get the following error
The Entity Framework provider type
'System.Data.Entity.SqlServer.SqlProviderServices,
EntityFramework.SqlServer' registered in the application config file
for the ADO.NET provider with invariant name 'System.Data.SqlClient'
could not be loaded. Make sure that the assembly-qualified name is
used and that the assembly is available to the running application

I created a sample project which is quite similar to your current setup minus the Model Layer/DAL separation.
I have three projects, DAL (which contains references to the EntityFramework.dll and the EntityFramework.SqlServer.dll), BLL which just calls a method in the DAL, and the UI which just calls the BLL methods.
I had to add the <configSections>, the <entityFramework>, and the <connectionStrings> portions of the app.config of the DAL into the UI's app.config.
When I ran the code the first time, I ran into the same error you ran into. So I looked into the debug folder of my UI Project and noticed that the EntityFramework.dll was copied into the folder due to the DAL's dependency on it. I also noticed that the EntityFramework.SqlServer.dll was NOT copied into the debug folder despite the DAL also having a dependency on it.
I copied the EntityFramework.SqlServer.dll into the debug folder of the UI Project then re-ran the project then, Viola! My code ran as expected.
It looks like the problem here is that one dll is not being copied into the UI Project debug folder as it is expected to.

Related

Exception thrown when using pre-generated views

In my project I have the following setup.
EF6 installed
Code first migration running
Views pre-generated using Entity Framework Power Tools
MVC project
This has been working fine up until now where after adding a new code first migration, and then regenerating the views, I can see the following error:
The current model no longer matches the model used to pre-generate the mapping views, as indicated by the fooClass.MappingHashValue property.
Pre-generated mapping views must be either regenerated using the current model or removed if mapping views generated at runtime should be used instead. See http://go.microsoft.com/fwlink/?LinkId=318050 for more information on Entity Framework mapping views.
There was no error generated at all when creating the migration, which is properly formed, and the database does manage to migrate perfectly well. The exception arises when running the MVC site.
For completeness sake, the model change is as following:
public class MyClass
{
[Key]
public int MyClassId
//various other properties
public int Version //newly added property
}
and the migration generated is:
public partial class AddingVersionNumber : DbMigration
{
public override void Up()
{
AddColumn("dbo.MyClass", "Version", c => c.Int(nullable: false));
}
public override void Down()
{
DropColumn("dbo.MyClass", "Version");
}
}
Reverting back to the previous migration, removing the migration changes and then regenerating the views works perfectly fine as well.
I have also tried just adding in a random model change to see if it was anything wrong with the specific table I was changing, but this test change failed with the same error. Seems that no matter how I change the model, the same error re-appears.
Another test I followed was to deleted the pre-generated views file from the project, but still the same exception is thrown.
Anyone else ever experienced anything similar?

IRepository in project which my Repository project references makes it hard to actually use them

I'm currently working in asp.net mvc 4 with EF5 and I'm trying to get my Dependency Injection to work with Ninject.
I've made 4 different projects in my solution:
Gui -> contains my MVC-project
BusinessLogic -> BusinessLogic
DataAccess -> my edmx-file and Repository (references Common)
Common -> Models, ViewModels and IRepository.
Now I'm trying to write this:
IRepository:
IQueryable<PictureSource> PictureSource { get; }
Repository:
IQueryable<PictureSource> IRepository.PictureSource
{
get { return context.PictureSource }
}
Now the problem is I can't call on PictureSource in my IRepository because it's an Entity from my EF, which is in my DataAccess. I've tried using automapper the following way in my Repository:
public IQueryable<PictureSourceModel> PictureSource()
{
Mapper.CreateMap<List<PictureSource>, List<PictureSourceModel>>();
return Mapper.Map<List<PictureSource>,List<PictureSourceModel>>
(context.PictureSource.ToList());
}
This gives errors about it beind a dbSet.
Any hints?
If you can't access some Model classes from your IRepository then you didn't apply your structure.
The PictureSourceModel class and all other Entities should be in your Common Project.
Then "as expected" all other projects will get access to these classes.
To be able to separate EF Entities to another Project you may consider to use Visual Studio Extension called "Ef DbContext Generator".
If you want more help tell me.
BTW: Try not to use AutoMapper in DAL. It should used in Gui project.
Update
To separate Entities to POCO classes
Install Visual Studio Extension called "Ef DbContext
Generator".
Open your edmx file and right click in empty area then chose "Add
Code Generation Item"
From the list select "Ef DbContext Generator"
Then just move the new file to another project
After that you should open .tt file to correct the .edmx file path

How to implement IDbContextFactory for use with Entity Framework data migrations

I am trying to use Entity Framework data migrations, as described in this post.
However, when I try to execute the Enable-Migrations step, I receive the following error in Package Manager Console:
The target context 'MyDataContext' is not constructible. Add a default constructor or provide an implementation of IDbContextFactory
So, I created a factory class that implements IDbContextFactory in the project that contains my DbContext class, but data migrations doesn't appear to recognize it.
Is there something that I should explicitly do to instruct data migrations to use this factory class?
I also hit this problem as i wrote my context to take a connection string name (and then used ninject to provide it).
The process you've gone through seems correct, here is a snippet of my class implementation if it's of any help:
public class MigrationsContextFactory : IDbContextFactory<MyContext>
{
public MyContext Create()
{
return new MyDBContext("connectionStringName");
}
}
That should be all you need.
Like #Soren pointed out, instead of using IDbContextFactory, not supported on some earlier EF Core releases (i.e. EF Core 2.1), we can implement IDesignTimeDbContextFactory<TContext>, which supports the missing ConnectionString parameter.
For a settings.json based aproach, which you can use with either of the referred interfaces, check #Arayn's sample which allows us to define "ConnectionStrings:DefaultConnection" value path
Update 1
According to #PaulWaldman's comment, on EF Core 5 support for IDbContextFactory was reintroduced. For further details, check his comment below.

Why is my WCF RIA context throwing FileNotFound exceptions during unit tests?

I'm trying to write unit tests involving my WCF RIA entity proxies and when I try to access an entity's parent or child properties through an association I get a FileNotFoundException when the WebContext class fails to load System.Xml.
For example, I have two entities defined in my web project in Entity Framework - Course and CourseUnit. A Course has many CourseUnit children. I'm not exposing any RIA contexts or anything to my ViewModels, they are all hidden behind interfaces. I'm using Moq to mock these interfaces and return the standard RIA entity proxies to my unit tests.
This works fine when I'm testing things like
Assert.AreEqual("title", course.Title)
where course is an instance of the RIA proxy. However, if I do something like
Assert.AreEqual(0, course.CourseUnits.Count)
I get the following exception
FileNotFoundException was unhandled by
user code Could not load file or
assembly 'System.Xml, Version=2.0.5.0,
Culture=neutral,
PublicKeyToken=7cec85d7bea7798e' or
one of its dependencies. The system
cannot find the file specified.
And similarly if I execute any code in a unit test that involved one of these relationships then the code throws the same exception. Basically if I ever try to access these properties with association relationships from my tests they break.
The exception actually occurs in generated code. It an be found in the file [webProjectName].g.cs in the partial class Course : Entity and happens in the CourseUnits getter.
Any ideas?
Edit - I added a reference to the EntityFramework assembly and the exception has changed to the same thing but System.ComponentModel.DataAnnotations instead of System.Xml. Needless to say I have tried referencing both assemblies in the unit test project, and it didn't work.

entity framework POCO template in a n-tiers design question

HI all
I was trying to follow the POCO Template walkthrough . And now I am having problems using it in n-tiers design.
By following the article, I put my edmx model, and the template generated context.tt in my DAL project, and moved the generated model.tt entity classes to my Business Logic layer (BLL) project.
By doing this, I could use those entities inside my BLL without referencing the DAL, I guess that is the idea of PI; without knowing anything about the data source.
Now, I want to extend the entities (inside the model.tt) to perform some CUD action in the BLL project,so I added a new partial class same name as the one generated from template,
public partial class Company
{
public static IEnumerable<Company> AllCompanies()
{
using(var context = new Entities()){
var q = from p in context.Companies
select p;
return q.ToList();
}
}
}
however visual studio won't let me do that, and I think it was because the context.tt is in the DAL project, and the BLL project could not add a reference to the DAL project as DAL has already reference to the BLL.
So I tried to added this class to the DAL and it compiled, but intelisense won't show up the BLL.Company.AllCompanies() in my web service method from my webservice project which has reference to my BLL project.
What should I do now? I want to add CUD methods to the template generated entities in my BLL project, and call them in my web services from another project.
I have been looking for this answer a few days already, and I really need some guides from here please.
Bryan
Mhhh, your layer architecture looks a bit like a spaghetti plate.
First in my opinion your POCO objects should be put in a different assembly which have no reference to any DAL, or else why bother about POCO ?
Second, static method in partial class don't look good, keep your poco objects very simple, and surrender the logic of it to repositories.
Take a look at that and all will be crystal clear:
http://thedatafarm.com/blog/data-access/agile-entity-framework-4-repository-part-1-model-and-poco-classes/
I don't think DAL should have a reference to BLL. I think it should be vice versa. BLL should be persistence ignorant.