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.
Related
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
In Entity Framework 5 model first, there seem to be some breaking changes due to the way the class files are generated (No more code generation, but T4 templates)
2 examples:
The generated context file doesn't implement IDisposable anymore
There isn't a constructor which takes a connectionstring anymore
Are there more breaking changes? And what is the solution to them?
The default code generated from a model in Entity Framework 5 now inherits DbContext instead of ObjectContext.
This still implements IDisposable, but if you're getting an error from a line of code similar to this:
using (var mymodel = new MyModelContext()) { ... }
...complaining about not implementing IDisposable, then your problem is most likely that your model is defined in a separate assembly that references EF5 and you have not added an EF5 reference to your project.
As Ladislav Mrnka has already mentioned in his answer, if you want to pass a connection string to the constructor you have to create your own constructor manually to do this.
If you want to switch Entity Framework back to the older style of generated code, which will automatically generate the constructor you're looking for, then follow these steps:
Click on the designer surface of your EDMX file, and look at the properties window. Find a property called "Code Generation Strategy" and set this to "Default" instead of "None". This will tell Visual Studio to start creating the code for your object model in MyModel.Designer.cs in one big file, this time using ObjectContext instead of DbContext.
Delete the following sub files from below your EDMX file: MyModel.Context.tt, MyModel.tt. These are the auto generated files that you don't want anymore. If you don't delete them you'll get class naming conflicts because your objects will be created twice.
The generated context file doesn't implement IDisposable anymore
IDisposable is still implemented by the parent context type. The generated type is still disposable.
There isn't a constructor which takes a connectionstring anymore
It now uses convention to get connection string but you can add your own constructor either to template or to your partial class part of the context.
Are there more breaking changes? And what is the solution to them?
It is whole breaking change because it uses different API - DbContext API instead of ObjectContext API which means different types, different methods, POCO entities etc. If you want to get back to original code generation you have to delete those T4 templates and enable code generation as described in .Designer.cs file but the current recommended way is to use POCOs and DbContext API.
I was having the same issue with the using statement needing a type that extended IDisposable... Turns out that I forgot to reference System.Data.Entity in my project... Added the reference and it fixed the problem.
Just clean and build the project, don't forget to add the reference to your entity.
few days ago i read tutorial about GenericRepository and Unit Of Work patterns http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application. I use web forms and i have EntityFramework CTP4 package installed. (I can't using EF 5).
I want to code generic repository for my project but i was stuck at this line:
this.dbSet = context.Set<TEntity>();
I know that this line doesn't work because a use ObjectContext in my project and database first approach. How can i deal with it? Can I code generic repository without migration to code first (which is not an option in my case) ?
This is the equivalent for ObjectContext:
this.dbSet = context.CreateObjectSet<TEntity>();
Now this creates an ObjectSet<TEntity> rather than a DbSet<TEntity>, but for your pattern you can use it in the same way.
UPDATE
The ObjectSet class does not have a utility method like that matches the Find() method of the DbSet. In order to "Get by key" you would need to construct an EntityKey and use the ObjectContext.GetEntityByKey(), unfortunately that's not a really simple thing to do.
There really isn't a simple way to tackle this, that I've found. In my case what I've done is to base all of my entities from a common class (using custom T4 templates to generate the classes from the model). And then I can add a generic constraint to my repositories, like:
public class MyRepository<TEntity> where TEntity : MyEntityBaseClass
And then my common base class has an Id field which is inherited by all the entities so I can can simply do:
return myObjectSet.SingleOrDefault(x => x.Id == myId);
I'm sure there are other approaches, that might be a good topic for another question.
1. You want to add the DbContextGenerator template to your visual studio templates:
2. After this make sure you clear out the default generation tool on your .edmx file.
3. Now you can implement the GenericRepository pattern as you wish.
I think my question is a long shot.
Lets say I have an attribute:
public sealed class MyCustomAttribute: ActionFilterAttribute
Used on a class method
[MyCustomAttribute]
public virtual ActionResult Options(FormCollection collection)
Now, I need to add a contructor's parameter
public MyCustomAttribute(IMyDependentObject dependentObject)
{
(...)
}
(You propably notice that it's some Asp.NET MCV code)
I would like to use DI to create this attribute. Asp.NET MVC code automatically create it and I don't know how/where I could write code to use Castle istead.
Any ideas?
As far a I konw castle does not support injection of existing objects, which makes it impossible to inject attributes as their construction is not under your control. Other IoC containers such as Ninject support injection of existing objects. They inject properties of your attribut filter. See http://github.com/ninject/ninject.web.mvc for an extension that exactly does what you need.
What you can do if you want to stay on castle is to inject your own ControllerActionInvoker derived from ControllerActionInvoker (AsyncControllerActionInvoker in case of async controller) into all controllers. In your own invoker you override GetFilters. Additionally to the Filters returned by the base you add FilterInfos that are created by castle.
The decision which filters infos are created and added can be achieved with various strategies e.g.:
Add an own custom attribute that contains the information e.g. name of a binding
A configuration file/database
May you consider switching to MVC3 this makes all a bit easier. As you can register your own FilterProvider which makes all much easier. In this FilterProvider you have to decide which filter info you want to add. See again the two strategies above. See http://bradwilson.typepad.com/blog/2010/07/service-location-pt4-filters.html for information about MVC3 and filters.
I'm trying to create a solution with layered architecture and self tracking entities.
I used the Entity Framework C# POCO Entity Generator i download from Extensions Online Gallery.
I separated the context.tt with the entities.tt on they're own class libraries.
Mapped the entities.tt to the Model. Now i need to make these classes inherit from a base class i created in another class library. Unfortunately i know nothing about changing the T4 template. Can someone help me on this problem to continue?
Thank you.
In your tt file search for
foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
And then look for a line that has
<#=Accessibility.ForType(entity)#> <#=code.SpaceAfter(code.AbstractOption(entity))#>partial class <#=code.Escape(entity)#><#=code.StringBefore(" : ", code.Escape(entity.BaseType))#>
Then add your interface to the end of it.