Suppose I have Employee class, should I put in the Employee class the add, delete, view, etc. methods? or should that class only for the getter/setter class?
which is better/acceptable/best practice?
Employee
-------------------
+int id (get/set)
+string name (get/set) (methods are called in another class)
Employee
-------------------
+int id (get/set)
+string name (get/set)
-add employee
-remove employee
This comes down to separation of concerns
When you are deciding these things, you need to use your intuition and think about it logically. What concerns an employee.
You have a class called Employee, then include in the Employee class everything that concerns an Employee. It doesn't make sense for an employee to be able to Add and Remove Employees to themselves. Maybe what you are looking for there is a class of Employees (plural) that will manage your employees ect ect ect.
But your Employee "will" have Name and Id and other things that concern it.
The goal here is to break up your concepts in to concrete real world concerns as much as possible, it makes it much easier to understand a design if you do
Assuming you have a database behind:
For similar purposes I have a base class for all entities that takes care of CRUD functionality and the ID. All entities inherit from this base class and take care of individual properties, like name, address, etc.
Also I have collections of all entities of the same type that manage the items in it.
Short Answer: Go with option 2
If you consider the separations of concerns, you should have an Employee to track the information of a single person and an Employee Repository for managing all of your employees. What makes up an record should be independent from how the record is stored/queried.
Employee class has information of employee, and the methods of employee. Looks like you are trying to maintain a collection of employees (assuming from add, delete employee requirement)
In that case add,delete,remove are not the responsibilities of employee class, rather the collection of employees.
Read on the OOP principles.
First 5 Principles of Object Oriented Design(S.O.L.I.D).
After Employee
public class Employee :ViewModelBase, IEditableObject
{
public int EmployeeID { get; set; }
public string FullName
{
get
{
return $"{this.Name} {this.Surname}";
}
}
private string _Name;
public string Name
{
get { return _Name; }
set
{
_Name = value;
OnPropertyChanged("Name");
}
}
}
After Create a Generics class with Repository For managment Add,Delete,Update etc...
public interface IRepository<T> where TEntity : class
{
IEnumerable<TEntity> GetUsers();
IQueryable<TEntity> SearchFor(Expression<Func<TEntity, bool>> predicate);
TEntity GetById(int id);
void Save(TEntity model);
void Delete(int id);
}
And Employee Base implementation Repository
public Class EmployeeManager : Repository<Employee>
{
public IEnumerable<TEntity> GetUsers()
{
//your code
}
public IQueryable<TEntity> SearchFor(Expression<Func<TEntity, bool>> predicate)
{
//your code
}
public TEntity GetById(int id)
{
//your code
}
public void Save(TEntity model)
{
//your code
}
public void Delete(int id)
{
//your code
}
public void DeleteAll(Employee[] employees)
{
//your code
}
}
Unity Repository Best Practices
I think you should have all the tools you need in one class, have multiple constructors to help load only the info as needed.
Related
I created a generic repository class that all my other repository classes are inheriting from. This is great, because it means almost all the plumbing is done one time for all repositories. I put a full explanation of what I'm talking about here, but here is the code for my GenericRepository (some code is removed for brevity):
public abstract class GenericRepository<T> : IGenericRepository<T> where T : class, new()
{
private IMyDbContext _myDbContext;
public GenericRepository(IMyDbContext myDbContext)
{
_myDbContext = myDbContext;
}
protected IMyDbContext Context
{
get
{
return _myDbContext;
}
}
public IQueryable<T> AsQueryable()
{
IQueryable<T> query = Context.Set<T>();
return query;
}
public virtual void Create(T entity)
{
Context.Set<T>().Add(entity);
}
public virtual void Update(T entity)
{
Context.Entry(entity).State = System.Data.EntityState.Modified;
}
}
As you see, I have a Create method and an Update method. It would be very convenient to have a "CreateOrUpdate" method, so I don't have to manually check for existing objects each time I have to save something to the database.
Each of my objects in Entity Framework have an "Id", but the challenge here is that the GenericRepository works with "T".
Now, with that rather long introduction, to my specific question.
How do I create a generic CreateOrUpdate method for my GenericRepository?
UPDATE
After Marcins response, I implemented the following generic methods in my GenericRepository. It will take some time before I can test that it works as expected, but it looks very promising.
public virtual bool Exists(Guid id)
{
return Context.Set<T>().Any(t => t.Id == id);
}
public virtual void CreateOrUpdate(T entity)
{
if (Exists(entity.Id))
{
var oldEntity = GetSingle(entity.Id);
Context.Entry(oldEntity).CurrentValues.SetValues(entity);
Update(oldEntity);
}
else
{
Create(entity);
}
}
The code above has no less than 3 roundtrips to the database when updating. I'm sure it can be optimized, but it wasn't really the exercise for this question.
This question handles that topic better:
An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key
Create a interface with Id property, implement it on every of your entities and add another generic constraint to your class:
public interface IEntity
{
int Id { get; set;}
}
And
public abstract class GenericRepository<T> : IGenericRepository<T> where T : class, IEntity, new()
With that, you'll be able to use Id property within your generic repository class.
Of course - Id don't have to be an int, it can be Guid as well.
I have code first implementation for flowing hierarchy,
BaseContact{
Public int Id{get;set;}
public string Name{get;set;}
//..
}
Person:BaseContact{
public string Designation{get;set;}
//..
}
Company:BaseContact{
public int NumOfEmployees{get;set;}
//..
}
I want to identify person or company with by using only the Id value? Currently I am using reflection to identify whether it is a person or company. Is there any other way to identify it without doing too much?
Without seeing how you initialised your classes I'm going to assume you have a table per concrete type approach.
You can't do it just from the ID, as you don't know which table the ID belongs to. ID 2 in "Person" table is a different entity to ID 3 in "Company". The only practical way to identify only from an ID is using a Table per Hierarchy approach and inspecting the type descriptor.
Some good references
http://weblogs.asp.net/manavi/archive/2011/01/03/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-3-table-per-concrete-type-tpc-and-choosing-strategy-guidelines.aspx
http://weblogs.asp.net/manavi/archive/2010/12/24/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-1-table-per-hierarchy-tph.aspx
You can also use a simple is statement instead of reflection. Ie if (entity is Company)
In your BaseContact (assume it is an abstract class) add abstract property which will be implemented by other two classes.Use Enum to identify the property type as follows.
public enum MyType
{
Person,
Company,
};
public abstract class BaseContact{
public abstract MyType ContactType{get;}
}
public class Person:BaseContact
{
public override MyType ContactType
{
get
{
return MyType.Person;
}
}
}
public class Company:BaseContact
{
public override MyType ContactType
{
get
{
return MyType.Company;
}
}
}
Use your BaseContact repository to retrieve entities and use enum for type separation.
I have a repository like that:
public class Repository<T> : IRepository<T> where T : class
{
private readonly IRepositoryContext _repositoryContext;
public Repository(IRepositoryContext repositoryContext)
{
_repositoryContext = repositoryContext;
_objectSet = repositoryContext.GetObjectSet<T>();
}
public virtual void Update(T entity)
{
ObjectSet.AddObject(entity);
_repositoryContext.ObjectContext.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);
_repositoryContext.SaveChanges();
}
}
Now that actually works for all scalar properties of the entity, but all the other entities that associated with properties of entity typeOf(T), don't care that entity state is modified, and EF simply adds new data.
So, if you do for example Repository<Student>.Update(), and you only changed the name, it will find the right Student and change his name, but it also will change the Campus, although you already have a Campus associated with that student, it will be created again with a different CampusId.
Show me please the correct way to do updates in this situation.
What I did when I wanted to follow generic approach was translated to your code something like:
public class Repository<T> : IRepository<T> where T : class
{
...
public virtual void Update(T entity)
{
if (context.ObjectStateManager.GetObjectStateEntry(entity).State == EntityState.Detached)
{
throw new InvalidOperationException(...);
}
_repositoryContext.SaveChanges();
}
}
All my code then worked like:
var attachedEntity = repository.Find(someId);
// Merge all changes into attached entity here
repository.Update(attachedEntity);
=> Doing this in generic way moves a lot of logic into your upper layer. There is no better way how to save big detached object graphs (especially when many-to-many relations are involved and deleting of relations is involved).
Here's a simple example of a problem I'm running across that is not meshing with some of the ideas presented here and other places regarding DDD.
Say I have an ASP.NET MVC 3 site that creates/manipulates a person. The controllers access an application service layer (PersonService) which in turn uses the domain entities (EF 4 POCO) and the PersonRepository to make changes and persist them. I'm leaving out all interfaces here for simplicity. Person is the root in this case and for simplicity only has email addresses (also assume email is not immutable and can be updated).
Option 1:
Try to stick with [my understanding] of the basics of DDD where behavior directly related to the entity is implemented as part of the entity (Person implements AddEmail, ChangeEmail, etc). The only problem with this, with the exception of the Add* methods, is that the Person would need to know about the context or entity framework pieces (which would remove any persistence ignorance) or need to use a "service" or repository to mark the email as modified.
// Person Service
public class PersonService {
// constructor injection to get unit of work and person repository...
// ...methods to add/update a person
public EmailAddress AddEmailAddress(int personId, EmailAddress email)
{
Person p = personRepository.Find(p => p.Id == personId).First();
p.AddEmail(email);
uow.SaveChanges();
return email;
}
public EmailAddress ChangeEmailAddress(EmailAddress email)
{
Person p = personRepository.Find(p => p.Id == personId).First();
p.ChangeEmail(email);
// change state of email object here so it's updated in the next line???
// if not here, wouldn't the Person entity have to know about the context
// or use a service?
uow.SaveChanges();
return email;
}
}
// Person Repository
public class PersonRepository
{
// generic repository implementation
}
// Person Entity
public class Person
{
public string Name { get;set; }
public IEnumerable<EmailAddress> EmailAddresses { get;set; }
public void AddEmail(EmailAddress email)
{
this.EmailAddresses.Add(email);
}
public void ChangeEmail(EmailAddress email)
{
EmailAddress orig = this.EmailAddresses.First(e => e.Id == email.id);
// update properties on orig
// NOW WHAT? [this] knows nothing about the context in order to change state,
etc, or do anything to mark the email add updated
}
}
// Email
public class EmailAddress
{
public string Email { get;set; }
public bool IsPrimary { get;set; }
}
Option 2:
Let the person service use the repository to add/update the email address and don't implement the behavior on the person entity. This is much simpler in the case of many to many relationships (for example, address, where two tables need to be updated to complete the work) but the model then becomes 'anemic' being just a bunch of getters and setters.
// Person Service
public class PersonService {
// constructor injection to get unit of work and person repository...
// ...methods to add/update a person
public EmailAddress AddEmailAddress(int personId, EmailAddress email)
{
Person p = personRepository.Find(p => p.Id == personId).First();
personRepository.AddEmail(personId, email);
uow.SaveChanges();
return email;
}
public EmailAddress ChangeEmailAddress(EmailAddress email)
{
personRepository.ChangeEmail(email);
uow.SaveChanges();
return email;
}
}
// Person Repository
public class PersonRepository
{
// generic repository implementation
}
// Person Entity
public class Person
{
public string Name { get;set; }
public IEnumerable<EmailAddress> EmailAddresses { get;set; }
}
// Email
public class EmailAddress
{
public string Email { get;set; }
public bool IsPrimary { get;set; }
}
Anyway, any thoughts on this?
Thanks, Brian
Option 1 is the way to go.
Reasoning is simple - changing e-mail addresses is domain concern. I bet Your domain experts have said that they will need to change emails. That automatically marks email changing piece of logic as business logic which is supposed to live in domain model. Objects primarily are defined by their behavior and not data that they hold.
Also - think twice before You choose to use unit of work pattern and wrap around everything in services. Aggregate roots are supposed to draw transaction boundaries and services usually are useless if they just wrap repository and domain object calls.
I would have something like this:
public class Person{
public Email Email{get;private set;}
public void SpecifyEmail(Email email){
//some validation, if necessary
EnsureEmailCanBeChanged();
//applying state changes
Email=email;
//raising event, if necessary
Raise(new EmailChanged(this));
}
public class EmailChanged:Event<Person>{
public EmailChanged(Person p):base(p){}
}
}
public class Email{
public Email(string email){
//validations (e.g. email format)
Value=email;
}
//implicit to string, explicit from string conversions
}
public class PersonController{
public ActionResult SpecifyEmail(int person, string email){
_persons.Get(person).SpecifyEmail((Email)email);
return RedirectToAction("Person",new{person});
}
}
I'm using NHibernate - it's smart enough to figure out what has changed since Person was persisted last time. Hard to say how exactly entity framework handles this.
I'm an NH user and may not know all EF limitations but generally speaking, whatever the limitations of ORM, entities should be left as clean as possible. Service Layer is already coupled with Data Access so no harm's done.
And I believe EF4 should know how to track collection changes. If not, then the best way is to leave the adding/removing logic in your Person entity and persist in PersonService.
BTW, your EmailAddress isn't an entity here, no Id (just a typo I guess). And how do you link your EmailAddress to Person?
I am trying to decide on an ORM tool for my project, and I am thinking about EF4.
What are the major (if any) annoyances/limitations with this product? Also, does it support caching?
Thanks
This is a good place to start. Granted he's one of the main contributors of NHibernate so that particular post may seem a little bit biased, but there are some good links and arguments in the comments.
And looks like someone asked a very similar question on SO a few months back.
The inability to use private backing fields for lazy loading collections. For example take this class:
public class Account
{
private IList<Customer> _customers = new List<Customer>();
public IEnumerable<Customer> Customers
{
get { return _customers ; }
}
public void AddCustomer(Customer customer)
{
//Perform some biz rules
_customers.Add(customer)
}
}
Access to the customers collection is restricted by using an IEnumerable collection and having a AddCustomer / RemoveCustomer methods on the class. Typically you want to do some business checking before adding or removing a new customer.
The current version of EF requires lazy loading collection types to be ICollection (or any type that implements ICollection). So the above class now would look like:
public class Account
{
private IList<Customer> _customers = new List<Customer>();
public virtual ICollection<Customer> Customers
{
get { return _customers ; }
}
public void AddCustomer(Customer customer)
{
//Perform some biz rules
_customers.Add(customer)
}
}
Using a public ICollection Customers completely destroys good OO design principals as consumers could directly access by calling the Add Operation on ICollection.
Account acc = new Account();
acc.Customers.Add(new Customer()); //Bad code
The original intention of the domain class was to use the public add method:
Account acc = new Account();
acc.AddCustomer(new Customer());
NHibernate can handle this scenario through configuration. I would very much like to see this scenario supported in the EF.
Note however there is a workaround for the this limitation by declaring the the backing field as protected and map it through configuration:
public class Account
{
protected virtual ICollection<Customer> _customers = new Collection<Customer>();
public IEnumerable<Customer> Customers
{
get { return _customers ; }
}
public void AddCustomer(Customer customer)
{
//Perform some biz rules
_customers.Add(customer)
}
}
But this won't work if your application has a layered architecture (i.e your domain model is separated from EF configuration classes) because protected types are not accessible to external classes.
In order for this to work requires the EF classes to be in the same assembly as your domain models!
Lazing loading collections require a public or protected type that implements ICollection.