I'm trying to use ASP.NET Boilerplate to handle my project and I have one serious problem.
I have 2 Models : Photo and Comment:
public class Comment : Entity<int>
{
[DataType(DataType.MultilineText)]
public string Text { get; set; }
public string Author { get; set; }
public int ItemID { get; set; }
public virtual Item Item { get; set; }
}
public class Item : Entity<int>
{
public string Title { get; set; }
public string Description { get; set; }
public ItemSourceType SourceType { get; set; }
public byte[] PhotoBytes { get; set; }
public string Url { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
}
Additionally I have created default OOB repository based on RepositoryBase<Item> and same for Comment.
The problem exists when I'm trying to get Item like this:
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Item item = _repoItems.Get(id.Value);
if (item == null)
{
return HttpNotFound();
}
return View(item);
}
When I'm debugging this code I can see that item has this exception in Comments property.
Am I missing something from ASP.NET Boilerplate or what?
Thanks for helping!
//Edit:
Full exception message:
{"The ObjectContext instance has been disposed and can no longer be used for operations that require a connection."}
I just stumbled across the same problem.
Seems to be that the UnitOfWork implementation creates and disposes a new DbContext for each "UnitOfWork"
So to fix that particular problem, try to inject "IUnitOfWorkManager"
and call
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
using(var uow = _unitOfWorkManager.Begin())
{
try
{
Item item = _repoItems.Get(id.Value);
if (item == null)
{
return HttpNotFound();
}
return View(item);
}
finally
{
uow.Complete()
};
}
}
if that works, consider calling "Begin()" in the constructor of your ApiController and "Complete()" in its "Dispose()" override.
Hope that helps!
No. The problem is most likely in your repository, the code of which you unfortunately have not included. If I had to guess, I'd say you're using something like the following in that repository method:
using (var context = new ApplicationContext())
{
// fetch something
}
Your Comments property is virtual, which means by default, Entity Framework will lazy load it, only actually issuing the query for that to the database once you try to access the property. However, by that point, you context has been disposed because the repository method has already finished its work, and your context was only available inside the using block.
There's a number of ways to fix this. You could eagerly load comments inside the the using block:
return context.Items.Include("Comments").Find(id);
However, that really just glosses over the problem. The best thing you can do is just not use using. Ideally, your context should be instantiated once and only once for each request. The easiest way to do that is to use a dependency injection container and add a constructor to your repository that accepts the context:
public class MyAwesomeRepository
{
private readonly ApplicationContext context;
public MyAwesomeRepository(ApplicationContext context)
{
this.context = context;
}
}
The configuration for your DI container will vary depending on which you choose to go with, but generally, you want to make sure that you bind your context class to request scope.
I had the similar issue with ASP.NET Boilerplate and figured out that this framework does all this DI magic properly only if you name your interfaces and classes in accordance with their naming conventions. You can somehow do it manually though, but you have to drill down into ABP architecture much deeper than you want.
A link posted by #ChrisPratt (see comments in his answer) says:
Naming conventions are very important here. For example you can change name of PersonAppService to MyPersonAppService or another name which contains 'PersonAppService' postfix since the IPersonAppService has this postfix. But you can not name your service as PeopleService. If you do it, it's not registered for IPersonAppService automatically (It's registered to DI framework but with self-registration, not with interface), so, you should manually register it if you want.
In my case, I had a service called ProductService implementing interface IProductAppService. It failed for me with ObjectDisposedException exception until I renamed my service to ProductAppService.
I don't think that OP still have this issue, but hopefully it will save few hours for the folks struggling with ABP like me. :-)
Related
Consider this simple one to many relationship in Entity Framework. One organisation holds many products.
public class Product
{
public int Id { get; set; }
[StringLength(20)]
public string Title { get; set; }
[StringLength(300)]
public string Description { get; set; }
public float Price { get; set; }
public DateTime CreationDate { get; set; }
public virtual Organisation Organisation { get; set; }
public Product()
{
CreationDate = DateTime.Now;
}
}
public class Organisation
{
public int Id { get; set; }
[StringLength(20)]
public string Title { get; set; }
[StringLength(400)]
public string Description { get; set; }
public DateTime CreationDate { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
If I have a (post) api call, accepting raw data in the body (json formatted text), which allows the user to create an organisation and as many products as they want, in the same call. How do I correctly save these data into the database using Entity Framework?
As far as I know I am using lazy loading (due to virtual keywords when setting relations in the models), so shouldn't it handle relations automatically? If I save the data like in the controller action below (the controller action for the post call). Will it work? And if it doesn't, what is the appropriate/best practice method for saving a model that contains a list of another model using Entity Framework.
public IHttpActionResult CreateOrganisation(Organisation org)
{
db.Organisations.Add(org);
db.SaveChanges();
return Ok(org);
}
Really can't seem to find this in the docs?
Well, i didn´t have time to try it, but looking at your code i see that there are some suggestions that i may point to you if you are looking for the best practices even if these don´t anwser your question:
Make your Web API Controller using the Async Task pattern to avoid dead locks:
public async Task<IHttpActionResult> CreateOrganisation(Organisation org)
Make the caller method, the business logic of your ef, as the same pattern above. In this case use the SaveChangesAsync() method. Don´t forget to use also the keyword await when calling any method as the example above within your controller.
Make the use of the separation of concerns. Apply the BL out of your Controller class.
Apply the SOLID principle. Dependency of inversion, letter D, for example using the Microsfot Unity IOC container, make the classes loosely coupled using abstract classes, interfaces, so after that apply the dependency of injection.
Try to use a View Model to valide the model instead of the domain class generated by the datafirst model or the code first model by the EF.
Last but not least, strongly typed!!!!
I hope these suggestions would help you.
Since you asked for "best practices", I'll tell you about a technique I had to work with back when EF's handling of object graphs was a little, shall we say "iffy"?
First, each physically stored entity has a corresponding DTO object. Part of the ViewModel (MVVM-speak) was the necessary DTO object(s) for that View. There were additional fields added to communicate State (what the UI did) for each entity. It looked something like this:
public class ProductDTO {
// Same fields, mostly
public string Action { get; set; } // A, C, D
}
public class OrganizationDTO {
// Same fields except children
public ICollection<ProductDTO> Products { get; set; }
public string Action { get; set; }
}
Based on non-blank Action in the top level DTO, POST, PUT or DELETE (A,C,D). UI sets the states of each entity. A modification to children counts as a "change" to the parent.
Then in my CRUD methods on the backend ... Admittedly, this is the sledgehammer approach.
public class OrganizationRepository : whatever interfaces {
public void Add (OrganizationDTO newOrg) {
if (newOrg.Action != "A") // Why are you here?
throw an exception (bad request)
context.Organizations.Add(Map DTO to entity here);
foreach (var item in newOrg.Products) {
switch (item.Action)
case "A":
ProductRepository.Add(item,newOrg.Id);
break;
case "C":
ProductRepository.Update(item,newOrg.Id);
break;
case "D":
ProductRepository.Delete(item);
break;
}
context.SaveChanges();
}
public void Update (OrganizationDTO oldOrg) {
if (newOrg.Action != "C") // Why are you here?
throw an exception (bad request)
context.Organizations.Attach(Map DTO to entity here);
foreach (var item in newOrg.Products) {
switch (item.Action)
case "A":
ProductRepository.Add(item,newOrg.Id);
break;
case "C":
ProductRepository.Update(item,newOrg.Id);
break;
case "D":
ProductRepository.Delete(item);
break;
}
context.SaveChanges();
return Ok();
}
}
This is not working/tested code. Just rough off-the-cuff. Have to handle FKs on adds. Add your mapping technique. Handle collisions, Try/Catch, etc.
I think your code is not well self-explaining.
If I'm a developer that looks at the method you posted here, I would simply not understand that i have the possibility to send nested-data.
I would make an iteration over the Products collection of the object "org" and add them to their EF collection, then late add the Organisation to its own.
Then, obviously, SaveChanges().
This would clearly distinguish this method that accept nested object, from another ipothetical that doesn't and simply saves my new empty Organisation.
I have a MVC solution :
In my different file :
Library.DataAccessLayer.LibraryContext.cs :
namespace Library.DataAccessLayer
{
public class LibraryContext : DbContext
{
public LibraryContext() : base("DefaultConnection")
{
}
public DbSet<Book> Books { get; set; }
public DbSet<Author> Authors { get; set; }
}
}
Library.DataAccessLayer.Models.Author.cs :
namespace Library.DataAccessLayer.Models
{
public class Author
{
[Key]
public int AuthorID { get; set; }
[Required]
[StringLength(50)]
[Display(Name = "First Name")]
public string FirstName { get; set; }
.........
}
}
Library.DataAccessLayer.Repositories.AuthorRepository.cs :
namespace Library.DataAccessLayer.Repositories
{
public class AuthorRepository : IDisposable, IAuthorRepository
{
private LibraryContext context;
public AuthorRepository(LibraryContext context)
{
this.context = context;
}
public IEnumerable<Author> GetAuthors()
{
return context.Authors.ToList();
}
public Author GetAuthorById(int id)
{
return .........
}
............
}
}
And in Library.Controllers.AuthorController :
namespace Library.Controllers
{
public class AuthorController : Controller
{
private IAuthorRepository authorRepository;
public AuthorController()
{
this.authorRepository = new AuthorRepository(new LibraryContext());
}
public ActionResult Index()
{
var authors = authorRepository.GetAuthors();
return View(authors);
}
}
}
1/ This architecture is coherent ?
2/ Is it really useful to declare interfaces for my repositories which are implemented in my repository classes ?
3/ In my AuthorRepository, the declaration and call of the LibraryContext is correct?
4/ In my AuthorController, my declaration and call of AuthorRepository is correct ?
5/ In which folder can we put the file LibraryContext ? (If necessary and useful)
6/ Is it good to group repositories interfaces and repositories class in the same folder? If not, how to separate and name the various folders ?
7/ How to improve that?
I need your advices.
Thanks
I find the architecture simple, which is good, maybe as your application grows you'll need more layers
Yeah, is really good, specially if you are going to use dependency injection, which leads to the next questions.
Your implementation is right, as for dependencies you should use some design patterns as, again, dependency injection or factory. All your dependencies should be instantiated outside.
This one should be the same as the previous one, the repository should be instantiated outside.
The structure is supposed to accommodate your needs, but I find the example in here pretty useful
Many developers do it that way, some also, and some others, like me, keep them in separate files, personally I create a 'contracts' folder alongside my repositories and keep the interfaces there.
The best way to find a convention that accommodates you is reading code from other developers, there you will find many styles, structures, architecture and pattern implementations.
I hope you find this useful, May the force be with you
This question is more fit to Codereview website, but I think it deserves an answer here:
Repositories are fine, but you should also consider defining a service layer. Services are responsible for aggregating information using repositories and providing this information using service models. Sending back data models (e.g. Authors) might lead to trouble because:
serialization can fail if navigation properties create cycles
you want to provide more information that is not related to data layer (e.g. some computed stuff)
Example:
class AuthorServiceModel
{
int AuthorId { get; set; }
string FirstName { get; set; }
// ...
}
class LibraryService : ILibraryService // if DI is used
{
public AuthorServiceModel GetAuthorById(int id)
{
// error handling/logging may be put here, if an invalid id is provided
var author = context.Authors.Get(id);
// auto mapping can be used to avoid the typing - check http://automapper.org/
var sm = new AuthorServiceModel { AuthorId = author.AuthorId, FirstName = author.FirstName };
return sm;
}
//
}
The controller will never have to know about your data access layer
2) Repositories unification - if most of your repositories are doing just the standard operations (get all, get by identifier, update entity, remove entity etc.), you may define a generic typed repository that helps you to avoid the repetition:
class Repository<T> : IRepository<T>
{
private LibraryContext context;
public IQueryable<T> All => context.Set<T>().AsQueryable();
public IQueryable<T> AllNoTracking => context.Set<T>().AsNoTracking();
public T Get(int id)
{
return context.Set<T>().Find(id);
}
// other methods
}
3) Implementing interfaces can be useful when using Dependency Injection - DI (e.g. Ninject). This removes some coupling between your classes and also allows automatic testing (bindings can be changed to mock objects). E.g.:
public class LibraryContext : DbContext, ILibraryContext
{
public LibraryContext() : base("DefaultConnection")
{
}
// other methods here
}
public class AuthorRepository : IDisposable, IAuthorRepository
{
private ILibraryContext context;
// the context will be injected and should not be provided by the caller, if DI is used
public AuthorRepository(ILibraryContext context)
{
this.context = context;
}
// other methods come here
}
public class AuthorController : Controller
{
// this allows for automatic injection based on defined bindings
[Inject]
public IAuthorRepository authorRepository { get; set; }
public AuthorController()
{
// no need for this, as DI takes care of the initialization
// also, controller does not have to know about your data access classes
// this.authorRepository = new AuthorRepository(new LibraryContext());
}
public ActionResult Index()
{
var authors = authorRepository.GetAuthors();
return View(authors);
}
}
4) Grouping of files is a matter of taste, but I usually recommend groping them semantically (all classes and interfaces that do similar jobs in a folder). Also, data context and repositories are quite coupled and they can reside in the same project/assembly.
Also, services can be separated in their own project/assembly.
NOTE: For a more thorough analysis, consider providing all the code related to your patterns and post your question on Codereview (they deal with complete and working code, not just fragments). It is a great chance that someone will cover all the topics from naming to the patterns).
My application has been built with ASP.NET MVC 4 and Web API. But I have a strange issue to share.
The corresponding code is below
public class MachinesController : ApiController
{
private GWData db = new GWData();
// GET api/Machines/5
public Machine GetMachine(int id)
{
Machine machine = db.Machines.Single(m => m.Id == id);
if (machine == null)
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
}
return machine;
}
Using following URL, I can examine my API Get method of a controller in Web API.
http://localhost/myweb/api/machines/1
And it worked but trying
http://localhost/myweb/api/machines/2
makes Web API hangs forever while memory usage of w3wp.exe keeps going up. So I had to eventually kill the w3wp.exe process. Further by making breakpoint inside of the GET method, I made sure that the hanging happens after getting right data and leaving the method.
How can I approach this kind of issue?
I should've found this cause earlier. This was a problem in serialization of Json. It took forever to serialize navigation properties of an entity if it has many related records. Of course, it was my fault to forget to disable lazy loading. Adding following code solved the problem.
public MachinesController()
{
db.ContextOptions.LazyLoadingEnabled = false;
}
I don't think your solution is correct. Instead you may want to have a model to view model structure, where view model object is flat and exposes only the properties you want to:
class Order
{
// properties you want to expose
public DateTime OrderDate { get; set; }
// navigation and other properties you don't want to expose
public Guid OrderId { get; set; }
public Customer Customer { get; set; }
public ICollection<Address> Addresses { get; set; }
public ICollection<Tax> Taxes { get; set; }
}
class OrderViewModel
{
public DateTime OrderDate { get; set; }
}
The easiest way to create one from another is to use AutoMapper.
Im having some problems saving an object (FeatureType) that have a 1-M relationship with Section.
public class FeatureType
{
public int Id { get; set; }
public string Name { get; set; }
[ForeignKey("SectionId")]
public Section Section { get; set; }
public virtual List<ItemType> ItemTypes { set; get; }
}
public class Section
{
public int Id { get; set; }
public string Name { get; set; }
public int Order { get; set; }
public virtual List<FeatureType> Features { get; set; }
}
If The ItemTypes are new i have no problem and the insert is done correctly.
But if i want to add some existing ItemTypes im getting this Error:
An entity object cannot be referenced by multiple instances of
IEntityChangeTracker.
I have been reading about this problem but i havent found a way to solve it, and it might be because of how its designed my application.
Whem im mappinig from my viewModel to my Model, im getting the section ID and getting the section Object from my SectionRepository as this:
private Section GetSection()
{
var section = _sectionRepository.GetSection(SectionId);
return section;
}
And this is what is giving me the problem, as the section is now been tracked by the SectionRepository that have its own context.
How can i solve this? I have tried just creating a new section with the existing ID but it just create me an empty object.
private Section GetSection()
{
var section = new Section{Id=SectionId};
return section;
}
UPDATE
To save my entity i just use :
_repository.Create(featureType.ToModel());
public FeatureType ToModel()
{
var ft = new FeatureType
{
Name = Name,
ControlType = (ControlType)ControlType,
Order = Order,
Required = Required,
RequiredText = RequiredText,
ItemTypes = GetItemTypes().ToList(),
Section = GetSection(),
};
return ft;
}
UPDATE 2: This is how i have my repositories, i wouldn't like to manage any EF in my controller but with some kind of repository or service.
public class EFBaseRepository
{
protected MyContext Db = new MyContext();
public void Dispose(bool disposing)
{
Db.Dispose();
}
}
public class EFFeatureTypeRepository : EFBaseRepository, IFeatureTypeRepository
{
public IQueryable<FeatureType> GetFeatureTypes
{
get { return Db.FeatureTypes.Include("Section").Include("ItemTypes"); }
}
public Message Create(FeatureType feature)
{
try
{
Db.FeatureTypes.Add(feature);
Db.SaveChanges();
return new Message();
}
catch (Exception e)
{
throw;
// return new Message(e, string.Format("Error Creating {0}", feature.GetType()));
}
}
//..Other Methods
}
You say that the SectionRepository has its own context. That is going to cause you problems. The repositories should share a context. The context is a combination of the unit of work and repository patterns. You need to separate the two patterns:
How to migrate towards unit-of-work and repository pattern
EDIT
You can avoid having the DbContext in the Controller by implementing your own Unit Of Work pattern.
public interface IUnitOfWork : IDisposable
{
ISectionRepository SectionRepository {get;}
//etc
int Save();
}
then in your controller:
public ActionResult Create(FeatureTypeCreate featureType)
{
_Uow.SectionRepository.Create(featureType.ToModel());
_Uow.Save(); //Saving is the responsibility of the Unit Of Work
//not the Repository
}
More references:
Implementing the Repository and Unit of Work
Repository and Unit of Work in Entity Framework
John Papa's original source code
Simply, the error you're getting means that the entities were returned from a different instance of your DbContext than from which they are now trying to be saved. Make sure that you're not doing something like using two different usings around your repository and that your repository always makes use of the same DbContext per instantiation.
In my solution I have two projects.
Project 1 (Core)
Mapping SQL to DTO using Dapper
Project 2 (WebUI - ASP.NET MVC 4)
Here I use a ViewModel per View.
Examples of a Controller
[HttpGet]
public ActionResult Edit(int id)
{
// Get my ProductDto in Core
var product = Using<ProductService>().Single(id);
var vm = new ProductFormModel(product);
return View(vm);
}
Examples of a ViewModel
public class ProductFormModel : BaseViewModel, ICreateProductCommand
{
public int ProductId { get; set; }
public int ProductGroupId { get; set; }
public string ArtNo { get; set; }
public bool IsDefault { get; set; }
public string Description { get; set; }
public string Specification { get; set; }
public string Unit { get; set; }
public string Account { get; set; }
public decimal NetPrice { get; set; }
public ProductFormModel(int productGroupId)
{
this.ProductGroupId = productGroupId;
}
public ProductFormModel(ProductDto dto)
{
this.ProductId = dto.ProductId;
this.ProductGroupId = dto.ProductGroupId;
this.ArtNo = dto.ArtNo;
this.IsDefault = dto.IsDefault;
this.Description = dto.Description;
this.Specification = dto.Specification;
this.Unit = dto.Unit;
this.Account = dto.Account;
this.NetPrice = dto.NetPrice;
}
public ProductFormModel()
{
}
}
Explanation:
I'll get my DTOs in my controller using a service class in the project (Core).
Then i create my ViewModel and pass the DTO to the constructor in ViewModel.
I can also use this view to add a new Product because my ViewModel can take a empty constructor.
Does anyone have experience of this. I wonder if I am in this way will have problems in the future as the project gets bigger?
I know this has nothing to do with Dapper. But I would still like a good way to explain my solution.
I think you will be fine using your current approach. More importantly, start out like this and refactor if you start to encounter problems related to your object mapping code (instead of thinking too much about it beforehand).
Another way to organize mapping logic that I use sometimes is to employ extension methods. That way, the mapping code is kept separate from the view model itself. Something like:
public static class ProductMappingExtensions
{
public static ProductFormModel ToViewModel(this ProductDto dto)
{
// Mapping code goes here
}
}
// Usage:
var viewModel = dto.ToViewModel();
Yet another approach would be to use a mapping framework like AutoMapper - this is a good fit in particular if your mapping logic is simple (lots of 1:1 mappings between properties).
But again, start simple and refactor when you need to.
I realize that this is a little bit late answer, but maybe it will help someone in the future.
This way of doing mapping between objects breaks the 'S' of the SOLID principles, because the responsibility of the ViewModel is to prepare data in its properties to be ready to use by the view and nothing else, therefore, mapping objects should not be on it's responsibilities.
Another drawback of this way is that it also breaks the 'Loose Coupling' OO principle as you ViewModel is strongly coupled with your DTO.
I think, even when we are in the very first step of the project, there are some importants OO principles that we should never break, so using mapper classes, either auto (AutoMapper, ValueInjecter ...) or manual, is definitely better.