I have .Net 4.0 application which use EntityFramework 5.0 to access data from MS SQL database.
I use database first approach. All tableas are mapped to POCO entities, which has additional properties which contains entities which is recieved from web service.
Database:
WH_Product (Id, NomenklatureId, SeriesId, Quantity)
Service have such data:
Nomenklature (Id, Name, Producer...)
Series (Id, Number, Date...)
POCO entity:
Product (Id, NomenklatureId, Nomenklature, SeriesId, Series, Quantity)
I have a problem with Repository realisation. I need to implement lazy loading for Nomenklature and Series properties.
I make ProductProxy class which implements such loading like this:
public class ProductProxy:Product
{
private Nomenklature _nomenklature;
public override Nomenklature Nomenklature
{
get
{
if (_nomenklature==null)
{
_nomenklature = <code for load Nomenklature from webService by base.NomenklatureId>
}
return _nomenklature;
}
}
private Series _series;
public override Series Series
{
get
{
if (_series==null)
{
_series = <code for load Series from webService by base.NomenklatureId>
}
return _series;
}
}
}
Then change Person class to PersonProxy class in DbContext.
public class ProductContext:DbContext
{
...
public DbSet<PersonProxy> Person {get; set;}
...
}
The load method:
public List<Person> GetPersons()
{
using (var ctx = new ProductContext())
{
var persons = ctx.Person.AsEnumerable().Cast<Person>().ToList();
return persons;
}
}
Question:
Is this a better way to realize GetPersons method without AsEnumerable().Cast()?
Is this another way of changing the entity type with the descendant proxy type?
The Proxy pattern is taking advantage of Polymorphism (one of 'The 3 Pillars of OOP'), the consumer of the object think it deals with a Person while in-fact he's dealing with a PersonProxy. that is possible because PersonProxy is a Person because it derives from it.
That's why you can write:
Person person = new PersonProxy();
Then in your case, your GetPersons() method could simply return IEnumerable<Person>, as follows:
public IEnumerable<Person> GetPersons()
{
using (var ctx = new ProductContext())
{
return ctx.Person;
}
}
If you value your entity classes being light, you could approach this differently, without putting loading logic in descendant proxies.
Instead, keep you entity classes simple and have them loaded externally after they're created (materialized).
Ladislav's answer shows how to get to the event that fires after every entity object is created. If you use this approach, subscribe to it with a handler, that distinguishes different entity classes and loads them appropriately - there's a lot of clean ways to do this.
Do note that if lazy loading of these properties is beneficial to you, this approach will probably not be useful.
Related
I am trying to update an entity using Entity Framework and save it to the database. When the update is called, my service method retrieves the DTO, assigns its the values of the entity object that the UI passed to it, and then saves it to the database. Instead of manually assigning those values, i'd like to use Automapper, however when I do this, the values that I am not mapping are updated to null. Is there a way in Entity Framework or Automapper to prevent this?
Service method finds the existing object in the database, assigns the new entity's properties to it, then saves:
public void Update(MyEntity updatedEntity, int id)
{
var existingObject = db.tblmyentity.Find(id);
existingObject.name = updatedEntity.name;
existingObject.address = updatedEntity.address;
existingObject.phone = updatedEntity.phone;
db.SaveChanges();
}
However, there are values stored in fields of this object not accessible by the UI, such as who modified the object and when. Using AutoMapper to simplify this code (shown below) causes these fields to update to null:
public void Update(MyEntity updatedEntity, int id)
{
var existingObject = db.tblmyentity.Find(id);
Mapper.Map(updatedEntity, existingObject);
db.SaveChanges();
}
A good practice is to create a (service, api) model that contains only the relevant properties that can be updated. E.g.:
public class MyEntityServiceModel
{
public string name { get; set; }
public string address { get; set; }
public string phone { get; set; }
}
// this looks differently in recent versions of AutoMapper, but you get the idea
Mapper.CreateMap<MyEntityServiceModel, MyEntity>();
// your update functions looks the same, except that it receives a service model, not a data model
Update(MyEntityServiceModel updatedEntity, int id)
{
// same code here
}
This approach has the following advantages:
you obtain what you are asking for
safety: you do not risk updating more properties than you should since the service model clearly specify the properties that should be updated
serialization: the service model is more appropriate if you need serialization (EF models may include unwanted navigation properties)
Update function consumer becomes unaware of the data persistence library you are using.
I'm having trouble figuring out how to edit an existing entity when posting it to my controller. When I save a new Person, it works just fine, because Id isn't set, so NHibernate views it as a new entity and attaches it to the session. However, when I try to edit an existing entity, the MVC model binder can't set the Id, even though the JSON being posted has it properly set. So even though it's an existing entity, NHibernate again sees it as a new one, and then throws an exception because I'm calling .Update() on an entity that's not in the database or session.
Here's the code I'm using (obviously Person has a lot more properties, I just left them off to keep the code short)
Person class:
public class Person
{
public virtual int Id {get; private set;}
//... other properties
}
The JSON being posted to my edit action
{"Id": 10}
And in the controller
public JsonResult EditPerson(Person person)
{
Session.Update(person);
return Json(new { success = true});
}
I was always under the impression that you had to load the entity to get it into the session so that you could edit it.
so you would need code like
var entity = Session.Get<Entity>(entity.Id);
//make your changes
Session.Save(entity);
Try
public virtual int Id {get; protected set;}
NHibernate uses proxies to load and set the properties of your classes, if your setter is private (rather than public or protected) the proxy (which inherits from your mapped class) cannot access it and assign the value it loaded from the database.
So perhaps I'm addressing this problem the wrong way, but I wanted to get the opinion from you fine people on StackOverflow about how to more correctly do this.
I've got a program that has to retrieve information from a repository around an Entity Framework 6.0 code-first context, do some work on the information contained and then it adds a new record to the database.
Anyway, here's the simplified look at the class I'm retrieving from EF through the repository:
public class Product
{
public int Id { get;set; }
public virtual ProductCategory Category { get;set; }
public string Name { get;set; }
}
I then build a ProcessedProduct with the following definition and pass in the previously retrieved Product as the BaseProduct:
public class ProcessedProduct
{
public int Id { get;set; }
public virtual Product BaseProduct { get;set; }
}
I use a repository layer that I saw on an EF lesson on Pluralsight and have purposed here. I've added all the relevant bits below:
public class MyContext : BaseContext<MyContext>, IMyContext
{
//Lots of IDbSets for each context
public void SetModified(object entity)
{
Entry(entity).State = EntityState.Modified;
}
public void SetAdd(object entity)
{
Entry(entity).State = EntityState.Added;
}
}
public class MyRepository : IMyRepository
{
private readonly IMyContext _context;
public MyRepository(IUnitOfWork uow)
{
_context = uow.Context as IMyContext;
}
public ProcessedProduct FindProcessedProduct(int id)
{
return _context.ProcessedProducts.Find(id);
}
public ProductCategory FindCategory(int id)
{
return _context.Categories.Find(id);
}
public int AddProcessedProductWithoutProduct(ProcessedProduct newRecord)
{
newRecord.Product = null;
Save();
return newRecord.Id;
}
public int UpdateProcessedProductWithProductButWithoutChildProperties(int processedProductId, int productId)
{
var processedProduct = FindProcessedProduct(processedProductId);
processedProduct.BaseProduct = FindProduct(productId);
processedProduct.BaseProduct.Category = null;
_context.SetModified(product);
Save();
return processedProduct.Id;
}
public int UpdateProductChildren(int processedProductId, int categoryId)
{
var processedProduct = FindProcessedProduct(processedProductId);
var category = FindCategory(categoryId);
processedProduct.BaseProduct.Category = category;
_context.SetModified(product);
Save();
return processedProduct.Id;
}
}
And finally, here's the portion that pulls it all together:
try
{
//Create the processed product without the product instance
var processedProductId = repo.AddProcessedProductWithoutProduct(finishedProduct);
//Now, update this processed product record with the product. This way, we don't create a
//duplicate product.
processedProductId = repo.UpdateProcessedProductWithProductButWithoutChildProperties(processedProductId, product.Id);
//Finally, update the category
processedProductId = repo.UpdateProductChildren(processedProductId, product.Category.Id);
//Done!
}
When I attempt to insert this ProcessedProduct into EF, it correctly creates the ProcessedProduct record, but it also creates a new Product and new Category row. I've tried manually changing the change tracking for each object so ProcessedProduct would be 'added' and the others would be either 'modified' or 'unchanged', but I would get foreign key reference exceptions thrown by Entity Framework.
My "fix" was to simply break this up into a number of different calls:
I create the new ProcessedProduct record, but I assign the Product value to null.
I query for that ProcessedProduct record with the Id, query for the appropriate Product with its Id and assign that Product to the newly retrieved ProcessedProduct record. However, I have to null out the Category property or else this will add a new duplicate Category record. I save and the ProcessedProduct record is modified.
Finally, I query the ProcessedProduct once more as well as the ProductCategory and then assign that ProductCategory to the Category property of the ProcessedProduct.BaseProduct. I can save once more and now I've created all the records I need without making any of the duplicates.
However, this approach seems quite convoluted since all I originally wanted to do is save the new parent record and simply not create duplicate child records. Is there a better way to go about doing this that I'm missing? Thanks!
Edit: And I guess the larger question is say I have a complex object with a whole bunch of these child complex objects. What's the easiest way to create a new parent without having to go through the entire graph of child objects to update the parent with them one layer at a time?
I highly recommend not setting Product & Category as navigation properties when editing. As you saw when you add the graph of processed product (with a product & category attached) to the EF context, it's marking everything in the graph as added and does inserts on everything.
The pattern I always recommend (and Nikolai also suggested in his comment, so up-vote his comment like I did :)) is to include the FK IDs in your entity and set those values, not the navigations. e.g.
newRecord.ProductId=theProductIdValue.
I've had many people cry "but foreign keys? ewwww! They will make my classes so dirty and impure!" but after they see how much easier it is to code things without tangling with the navigations in these scenarios, they have come back to say "okay, it was worth it!"
BTW if you are talking about my EF in the Enterprise course, I have a whole module about dealing with this problem...it's called something bout graphs in disconnected scenarios. :)
I'm a junior web developer trying to learn more every day.
What it the best practice for you guys to performe MVC repository pattern with Linq?
The one I use:
Create extra clases with the exact name of my .tt files with CRUD method like getAll(), getOne(), Update(), Delete() filling my own class with the entity framework and returning this, or using the entity framework crude
this is an example of what I'm actually doing.
this is my getAll method of my class for example User
public class CEmployee : CResult
{
public string name{get;set;}
public string lastname{get;set;}
public string address{get;set;}
//Extracode
public string Fullname // this code is not in the .tt or database
{
get
{
return name + lastname;
}
}
public <List>CEmployee getAll()
{
try
{
var result = (from n in db.Employee
select new CEmployee // this is my own class I fill it using the entity
{
name = n.name,
lastname = n.lastname,
address = n.address
}).ToList();
if (result.Count > 0)
{
return result;
}
else
{
return new List<CResult>
{
new CResult
{
has_Error = true,
msg_Error = "Element not found!!!!"
}
}
}
}
catch
{
return Exception();
}
}
}
that the way I do all thing I return a filled of my type, but on the web I see that people return the entity type normaly, But I do this to manipulate my response, And if I want to return extra information I just have to neste a list for example, whats the best way guys, return mytype or return the entity type ?
PD, I also use this class like my ViewModel.And I do this for all my classes.
One of the projects I am currently one uses Dependency Injection to setup the DAL (Data Access Layer.) We also are using an n-Tier approach; this separates the concern of the repository from the Business Logic and Front End.
So we would start with 4 or so base projects in the application that link to each other. One of that handles the Data Access, this would be your repository; read up on Ninject for more info on this. Our next tier is our Domain which houses the Entities built by the t4 template(.tt files) and also our DTO's (data transfer objects which are flat objects for moving data between layers.) Then we have a service layer, the service layer or business logic layer holds service objects that handle CRUD operations and any data manipulation needed. Lastly we have our front end which is the Model-View-ViewModel layer and handles the controllers and page building.
The MVVM calls the services, the service objects call the data access layer and Entity Framework works with Ninject to access the data and its stored in the DTO's as it is moved across layers.
Now this may seem overly complex depending on the application you are writing, this is built for a highly scalable and expandable web application.
I would highly recommend going with a generic repository implementation. The layers between your repository and the controller vary depending on a number of factors (which is kind of a broader/bigger topic) but the generic repository gets you going on a good implementation that is lightweight. Check out this article for a good description of the approach:
http://www.asp.net/mvc/tutorials/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
Ideally in a MVC application, you will want to repositories in a different layer like in a separate project, let's call it Data layer.
You will have an IRepository interface that contain generic method signatures like GetAll, GetById, Create or UpdateById. You will also have abstract RepositoryBase class that contain shared implementation such as Add, Update, Delete, GetById, etc.
The reason that you use an IRepository Interface is, there are contracts for which your inherited repository class, such as EmployeeRepository in your case, need to provide concrete implementations. The abstract class serves as a common place for your shared implementation (and override them as you need to).
So in your case, what you are doing using LINQ with your DbContext is basically correct, but implementation like your GetAll method should be part of the generic/shared implementation in your abstract class RepositoryBase:
public abstract class RepositoryBase<T> where T : class
{
private YourEntities dataContext;
private readonly IDbSet<T> dbset;
protected RepositoryBase(IDatabaseFactory databaseFactory)
{
DatabaseFactory = databaseFactory;
dbset = DataContext.Set<T>();
}
protected IDatabaseFactory DatabaseFactory
{
get;
private set;
}
protected YourEntities DataContext
{
get { return dataContext ?? (dataContext = DatabaseFactory.Get()); }
}
public virtual T GetById(long id)
{
return dbset.Find(id);
}
public virtual T GetById(string id)
{
return dbset.Find(id);
}
public virtual IEnumerable<T> GetAll()
{
return dbset.ToList();
}
}
I would suggest you need to think about whether or not to return an error result object like CResult, and think about if your CEmployee and CResult should exist in this parent-child relationship. Also think about what you want to do with your CResult Class. It seems to me your CEmployee handles too many tasks in this case.
I'm new to C# and ASP.NET MVC and i'm trying to understand the repository pattern. I've read a whole lot of articles, but I just don't understand how to use it. I'm currently using LINQ to SQL to access my SQL Server 2005 database and for testing purposes I created two tables. I have an Employees table and an EmployeeContacts table. The pk of both tables is UserName.
Employees
UserName
LastName
FirstName
Position
Email
Status
HireDate
EmployeeContacts
UserName
Contact1
Contact1Phone
Contact1Relationship
There is a one to one relationship between the two tables. An employee can be added, updated, and deleted and so can the data in the EmployeeContacts table.
So would I create a base repository to be used by both entities or should I create a repository for each entity separately? If anybody would be willing to show me some code that would be great.
So far, I have this Employee repository. I also have one for EmployeeContacts.
namespace MvcDirectoryLINQ.Models
{
public class EmployeeRepository
{
private TestDB_DataDataContext db = new TestDB_DataDataContext();
private UserName u = new UserName();
//
// Query Methods
public IQueryable<Employee> FindAllEmployees()
{
return db.Employees;
}
public IQueryable<Employee> FindRecentEmployees()
{
DateTime myDate = DateTime.Today.AddMonths(-6);
return from empl in db.Employees
where empl.HireDate >= myDate
orderby empl.HireDate
select empl;
}
public Employee GetEmployee(string UserName)
{
return db.Employees.SingleOrDefault(d => d.UserName == UserName);
}
//
// Insert/Delete Methods
public void Add(Employee employee)
{
// get the UserName which is created from the email
employee.UserName = u.ReturnUserName(employee.Email);
//Insert the new employee into the database
db.Employees.InsertOnSubmit(employee);
db.EmployeeContacts.InsertOnSubmit(employee.EmployeeContact);
}
public void Delete(Employee employee)
{
db.EmployeeContacts.DeleteOnSubmit(employee.EmployeeContact);
db.Employees.DeleteOnSubmit(employee);
}
//
// Persistence
public void Save()
{
db.SubmitChanges();
}
}
}
I have a class for an EmployeeFormViewModel:
namespace MvcDirectoryLINQ.Models
{
public class EmployeeFormViewModel
{
//Properties
public Employee Employee { get; private set; }
public EmployeeContact EmployeeContact { get; private set; }
//Constructor
public EmployeeFormViewModel(Employee employee, EmployeeContact employeeContact)
{
Employee = employee;
EmployeeContact = employeeContact;
}
}
}
Code for EmployeeController:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(string UserName, FormCollection formValues)
{
Employee employee = employeeRepository.GetEmployee(UserName);
EmployeeContact employeecontact = employeecontactRepository.GetContact(UserName);
try
{
UpdateModel(employee);
UpdateModel(employeecontact);
employeecontactRepository.Save();
employeeRepository.Save();
return RedirectToAction("Details", new { UserName = employee.UserName });
}
catch
{
foreach (var issue in employee.GetRuleViolations())
{
ModelState.AddModelError(issue.PropertyName, issue.ErrorMessage);
}
return View(new EmployeeFormViewModel(employee, attendingID));
}
}
In my View, i inherit from #model MvcDirectoryLINQ.Models.EmployeeFormViewModel. My Employee data saves correctly but the EmployeeContacts don't and I have no idea why.
Am I implementing the repository pattern correctly?
The main goal when using the Repository Pattern (as far as I understand it) is to decouple your application from using a specific Data Access Layer. You haven't done that here because you create I can see that your EmployeeRepository class does not implement an interface. You really want to have something like EmployeeRepository : IEmployeeRepository
Then, in your Controller code, you can pass around an IEmployeeRepository instead of working concretely with your EmployeeRepository. This will give you two benefits:
Should you ever need to switch the backend code, you only need to make another class that implements the interface.
When you go to test your Controllers, you can pass around a so called mock object that implements the interface instead of hitting the actual database, which slows your tests down and also breaks Unit Testing.
Another thing I noticed is that you spin up a DataContext inside your repository. If you wanted to make changes to multiple different types of objects you would therefore have multiple DataContexts open, which I don't think is what you want, since your changes won't be transactional. You may want to look into the Unit of Work Pattern for a solution.
When learning about a pattern, try to figure out the main benefit first before trying to implement it. In some cases it may not make sense. Please let me know if you would like me to elaborate on anything. Good luck.
So would I create a base repository to be used by both entities or should I create a repository for each entity separately?
The general rule when using the repository pattern is that there should be one repository class per each primary entity type. Can the EmployeeContacts live independently of any Employee? If so, they should have their own repository. Are them always related to an Employee? If so, manage them by using the Employee repository itself.