Update an entity property when another property changes (after entity is initialized) - c#

I am using Entity Framework and Code First approach in a WPF MVVM application backed by a SQL CE database. I am trying to design a model class that can simply update one of its property values in response to another one of its property values changing. Basically, I am looking for a way to define a poco that is "self-tracking" after the instance is initialized by EF. If the answer involves abandoning Code First, then maybe that is the only viable route (not sure). A basic example:
class ThingModel
{
public int Id { get; set; }
public bool OutsideDbNeedsUpdate { get; set; }
private string _foo;
public string Foo
{
get { return _foo; }
set
{
if (_foo != value)
{
_foo = value;
OutsideDbNeedsUpdate = true;
}
}
}
}
However, the problem with the above is that whenever DbContext is initializing an instance at runtime and setting the fields, my class is prematurely setting the dependent field in response. In other words, I am searching for a simple pattern that would allow my poco class to ONLY do this special change tracking after EF has finished initializing the fields on an instance.
I realize I could do something like the solution here
but my business case requires that this special change tracking be decoupled from the EF change tracking, in other words, I require the ability to SaveChanges regardless of the state of the HasChanges property above. This is because I would like to be able to periodically check the HasChanges property on my entities and in turn update dependent values in an outside database (not the same one backing the EF DbContext) and many changes/saves may happen to the EF DB between pushes to the outside DB. Hence the reason I was hoping to just persist the flag with the record in my DB and reset it to false when the periodic update to the outside DB occurs.

After your edit I think you can use the ObjectMaterialized event.
This event is raised after all scalar, complex, and reference properties have been set on an object, but before collections are loaded.
Put this in the constructor of your DbContext:
((IObjectContextAdapter)this).ObjectContext.ObjectMaterialized +=
HandleObjectMaterialized;
And the method:
private void HandleObjectMaterialized(object sender, ObjectMaterializedEventArgs e)
{ }
Now the question is, what to put in the method body? Probably the easiest solution is to define an interface
interface IChangeTracker
{
bool Materialized { get; set; }
bool OutsideDbNeedsUpdate { get; }
}
and let the classes you want to track implement this interface.
Then, in HandleObjectMaterialized you can do:
var entity = e.Entity as IChangeTracker;
if (entity != null)
{
entity.Materialized = true;
}
After this you know when you can set OutsideDbNeedsUpdate internally.
Original text
Generally it is not recommended to have properties with side effects (well, more exact, with more side effects than changing the state the represent). Maybe there are exceptions to this rule, but most of the time it is just not a good idea to have dependencies between properties.
I have to guess a bit what you can do best, because I don't know what your real code is about, but it might be possible to put the logic in the getter. Just an example:
public State State
{
get { return this.EndDate.HasValue ? MyState.Completed : this._state; }
set { this._state = value; }
}
This does not remove the mutual dependencies, but it defers the moment of effect to the time the property is accessed. Which in your case may be not sooner than SaveChanges().
Another strategy is making a method that sets both properties at once. Methods are expected to have side effects, especially when their names clearly indicate it. You could have a method like SetMasterAndDependent (string master).
Now methods are not convenient in data binding scenarios. In that case you better let the view model set both properties or call the method as above.

Related

Attaching entities to EF context, without loading them, without sacrificing DDD

In DDD it is customary to protect an entity's properties like this:
public class Customer
{
private Customer() { }
public Customer(int id, string name) { /* ...populate properties... */ }
public int Id { get; private set; }
public string Name { get; private set; }
// and so on...
}
EF uses reflection so it can handle all those privates.
But what if you need to attach an entity without loading it (a very common thing to do):
var customer = new Customer { Id = getIdFromSomewhere() }; // can't do this!
myContext.Set<Customer>().Attach(customer);
This won't work because the Id setter is private.
What is a good way to deal with this mismatch between the language and DDD?
Ideas:
make Id public (and break DDD)
create a constructor/method to populate a dummy object (makes no sense)
use reflection ("cheat")
???
I think the best compromise, is to use reflection, and set that private Id property, just like EF does. Yes it's reflection and slow, but much faster than loading from the database. And yes it's cheating, but at least as far as the domain is concerned, there is officially no way to instantiate that entity without going through the constructor.
How do you handle this scenario?
PS I did a simple benchmark and it takes about 10s to create a million instances using reflection. So compared to hitting the database, or the reflection performed by EF, the extra overhead is tiny.
"customary" implicitly means it's not a hard set rule, so if you have specific reasons to break those rules in your application, go for it. Making the property setter public would be better than going into reflection for this: not only because of performance issues, but also because it makes it much easier to put unwanted side-effects in your application. Reflection just isn't the way to deal with this.
But I think the first question here is why you would want the ID of an object to be set from the outside in the first place. EF uses the ID primarily to identify objects and you should not use the ID for other logic in your application than just that.
Assuming you have a strong reason to want to change the ID, I actually think you gave the answer yourself in the source you just put in the comments:
So you would have methods to control what happens to your objects and
in doing so, constrain the properties so that they are not exposed to
be set or modified “willy nilly”.
You can keep the private setter and use a method to set the ID.
EDIT:
After reading this I tried doing some more testing myself and you could have the following:
public class Customer
{
private Customer() { }
public Customer(int id) { /* only sets id */ }
public Customer(int id, string name) { /* ...populate properties... */ }
public int Id { get; private set; }
public string Name { get; private set; }
// and so on...
public void SetName(string name)
{
//set name, perhaps check for condition first
}
}
public class MyController
{
//...
var customer = new Customer(getIdFromSomewhere());
myContext.Set<Customer>().Attach(customer);
order.setCustomer(customer);
myContext.SaveChanges(); //sets the customer to order and saves it, without actually changing customer: still read as unchanged.
//...
}
This code leaves the private setters as they were (you will need the methods for editing of course) and only the required changes are pushed to the db afterwards. As is also explained in the link above, only changes made after attaching are used and you should make sure you don't manually set the state of the object to modified, else all properties are pushed (potentially emptying your object).
This is what I'm doing, using reflection. I think it's the best bad option.
var customer = CreateInstanceFromPrivateConstructor<Customer>();
SetPrivateProperty(p=>p.ID, customer, 10);
myContext.Set<Customer>().Attach(customer);
//...and all the above was just for this:
order.setCustomer(customer);
myContext.SaveChanges();
The implementations of those two reflection methods aren't important. What is important:
EF uses reflection for lots of stuff
Database reads are much slower than these reflection calls (the benchmark I mentioned in the question shows how insignificant this perf hit is, about 10s to create a million instances)
Domain is fully DDD - you can't create an entity in a weird state, or create one without going through the constructor (I did that above but I cheated for a specific case, just like EF does)

Who is responsible for entity's mutation when domain event is raised? DDD

I've been learning about CQRS/ES. Looking at small example projects I often see events mutating the entity state. For instance If we look at the Order aggregate root:
public class Order : AggregateRoot {
private void Apply(OrderLineAddedEvent #event) {
var existingLine = this.OrderLines.FirstOrDefault(
i => i.ProductId == #event.ProductId);
if(existingLine != null) {
existingLine.AddToQuantity(#event.Quantity);
return;
}
this.OrderLines.Add(new OrderLine(#event.ProductId, #event.ProductTitle, #event.PricePerUnit, #event.Quantity));
}
public ICollection<OrderLine> OrderLines { get; private set; }
public void AddOrderLine(/*parameters*/) {
this.Apply(new OrderLineAddedEvent(/*parameters*/));
}
public Order() {
this.OrderLines = new List<OrderLine>();
}
public Order(IEnumerable<IEvent> history) {
foreach(IEvent #event in history) {
this.ApplyChange(#event, false);
}
}
}
public abstract class AggregateRoot {
public Queue<IEvent> UncommittedEvents { get; protected set; }
protected abstract void Apply(IEvent #event);
public void CommitEvents() {
this.UncommittedEvents.Clear();
}
protected void ApplyChange(IEvent #event, Boolean isNew) {
Apply(#event);
if(isNew) this.UncommittedEvents.Enqueue(#event);
}
}
when OrderLineAddedEvent is applied it mutates Order by adding new order line. But I don't understand these things:
if it is a right approach how then the changes made are persisted?
Or should I publish the event somehow to a corresponding handler from Order? How do I implement this technically? Should I use a service bus to transmit events?
I am also still experimenting with ES so this is still somewhat of an opinion rather than any guidance :)
At some stage I came across this post by Jan Kronquist: http://www.jayway.com/2013/06/20/dont-publish-domain-events-return-them/
The gist of it is that event should be returned from the domain rather than being dispatched from within the domain. This really struck a chord with me.
If one were to take a more traditional approach where a normal persistence-oriented repository is used the Application Layer would handle transactions and repository access. The domain would simply be called to perform the behaviour.
Also, the domain should always stick to persistence ignorance. Having an aggregate root maintain a list of events always seemed somewhat odd to me and I definitely do not like having my ARs inheriting from some common base. It does not feel clean enough.
So putting this together using what you have:
public OrderLineAddedEvent AddOrderLine(/*parameters*/) {
return this.Apply(new OrderLineAddedEvent(/*parameters*/));
}
In my POC I have also not been using an IEvent marker interface but rather just an object.
Now the Application Layer is back in control of the persistence.
I have an experimental GitHub repository going:
https://github.com/Shuttle/shuttle-recall-core
https://github.com/Shuttle/shuttle-recall-sqlserver
I haven't had time to look at it for a while and I know I have already made some changes but you are welcome to have a look.
The basic idea is then that the Application Layer will use the EventStore/EventStream to manage the events for an aggregate in the same way that the Application Layer would use a Repository. The EventStream will be applied to the aggregate. All events returned from the domain behaviours would be added to the EventStream after which it is persisted again.
This keeps all the persistence-oriented bits out of the domain.
An Entity doesn't update itself magically. Something (usually a service) will invoke the update behaviour of the entity. So, the service uses the entity which will generate and apply the events, then the service will persist the entity via a repository, then it will get the new events from the entity and publish them.
An alternate method is when the Events Store itself does the publishing of the events.
Event Sourcing is about expressing an entity state as a stream of events, that's why the entity updates itself by generating and applying events, it needs to create/add the changes to the events stream. That stream is also what it's stored in the db aka the Event Store.
Lately I am splitting my entities into two objects.
First is what I call a Document object. This is mostly a state only, ORM class with all the configuration related with how the information is persisted.
Then I wrap that Document with an Entity object, which is basically a mutation service containing all the behaviour.
My entities are basically stateless objects except of course for the contained document, but in any case, I mostly avoid any exposure to the outside world.

Is it bad practice to use accessors from within a class? [duplicate]

This question already has answers here:
Accessing members in your own class: use (auto)properties or not?
(5 answers)
Closed 9 years ago.
So I have a simple class, User, which is something like this (ignore horrible whitespace use, wanted to keep it brief to read online):
public class User
{
private string username;
public string Username
{
get
{
return username;
}set{
if(Validate.usernameIsValid(value)){username = value;}
else{throw new InvalidArgumentException("Username is invalid");}
}
}
//some more fields
public User(String argUsername)
{
this.Username = argUsername;
//OR validate again before:
username = argUsername;
}
}
Is it better to use the public accessor within the class to use its validation? Or is that bad practice and in that case, should I re-validate before setting the private username field?
I'd recommend using the public setter over local setting of the variable, simply because there'll be one place - the setter - where all the logic related to validation is handled. But this is only effective if you follow this convention every where within the class and all the derived versions strictly.
One cannot assume that a member variable is not manipulated elsewhere in the class ( or its derived versions, if it is protected). Imagine another programmer debugging an error related to username validation. It can be a pleasant surprise to find out upon search, that all validations take place via the setter - so she doesn't haven't to debug multiple validation logic.
The answer depends on where the data is coming from. Since the driving point behind using a setter is to avoid duplicating your validation code, you have two basic cases:
When the data is coming from outside your class (i.e. through a method parameter, as in your example) then you should call the setter, which would perform validation for you.
When the data has been "sanitized" at the point where you are ready to assign, go straight to the variable, bypassing the validation.
The former case extends to situations where you read user input.
The later case includes situations where you restore object's state from a snapshot, or generate object's state internally. For example, if your setter has null/empty string validation, and your method wants to set the string to a string representation of a GUID, it's OK to skip the setter.
In most cases I use the public property because what is done there usualy needs to be done all the time. But there are exceptions (for example if validations needs to be done once). So you can't really can't tell in general.
Using public accessors within a class is OK, as well as using any public method. (After all, properties are just syntax sugar for getter/setter methods.)
Using accessors internally might be preferred if accessing a property from within a class has the same semantics as accessing it from outside.
In addition, accessors bring a consistent way to deal with regular and auto-implemented properties. (Auto-implemented ones just do not expose backing fields explicitly.)
Also, outside of constructors, almost for sure, accessors should be used for virtual properties.
Direct use of backing field is needed rather for back-door property manipulations.
But there is no general rule which approach to choose.
actually you have done well, self encapsulate fields make you set the value of property based on your needs easily: for example take a look at this:
private readonly ProductManufacturer _productManufacturer = new ProductManufacturer();
private readonly IList<ProductCategory> _productCategories = new List<ProductCategory>();
public ProductManufacturer ProductManufacturer
{
get { return _productManufacturer; }
}
public IEnumerable<ProductCategory> ProductCategory
{
get { return _productCategories; }
}
now you can get the list of product category list else where, or you can only do some other operation on product category like this:
public void AddProductCategory(ProductCategory productCategory)
{
_productCategories.Add(productCategory);
}
for more information about self encapsulate fields take a look at this:
http://www.refactoring.com/catalog/selfEncapsulateField.html

How to Design whether a Class Property has Changed?

I have a class with about 20 properties but I'd simplify it for this question:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
}
I'd like to have a class or property that identifies whether my class is dirty. By this I mean to identify whether any of its values have changed?
There are 3 design approaches I can take:
1)
When setting the property inside the class, I check whether the property IsDirty.
public string Name
{
get { return this._name; }
set { if (this._name != value) { this.IsDirty = true; this._name = value; }
}
2)
When setting the property from outside the class, I check whether the property IsDirty.
e.g.
if (p.Name != newName)
{
p.IsDirty = true;
p.Name = newName;
}
This approach forces me to add lots of ifs in the client class. Some properties are even collections or even reference objects so the number of lines would be increased even.
3)
When the object is ready to be saved, then I check whether any properties IsDirty by getting a cloned object and checking the equality.
This would have a poorer performance as I would have to clone or load again the original object then compare the properties one by one.
Which one is the best design? or is there any other design pattern that can help with this?
Another option would be to Implement the INotifyPropertyChanged Interface.
Please note that this will help you make thing more tidy and your API clearer, but as far as internal implementation regarding keeping track after changes, It is still up to you to implement. I think this goes along best with your Option #1
Option 1 is clearly best: it puts the responsibility of tracking dirtiness where it belongs: inside the object. Option 2 is out because as you mentioned, you are forcing this responsibility onto the clients of your classes. And option 3 has the additional problem as you mentioned of performance.
Incidentally, you should look into a proxy implementation using DynamicProxy. This will allow your code to look like this:
public class Product
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
}
and with the judicious use of interceptors, you can get the behaviour you want. You can write an interceptor to intercept any "sets" and do some logic inside, such as setting an IsDirty flag.
Another idea would be to make this a GoF Observable and let interested Observer parties register their interest in changes. It's a more event-based approach.
This is the best solution and complies with SRP principle very nicely, I created the below classes:
ProductWithChangeDetection; this uses the Decorator pattern to add this new feature to an existing product object
ProductChangeDetector; this contains logics for checking and notification. Currently only exposes ChangeDetected property but if more complexity needed one should implement INotifyPropertyChange interface.
ProductEquitable; this implements IEquitable and has some overloads for checking whether two objects/properties are equal

Validate entities when adding to a navigation property

I have an entity with a collection property that looks something like this:
public class MyEntity
{
public virtual ICollection<OtherEntity> Others { get; set; }
}
When I retrieve this entity via the data context or repository, I want to prevent others adding items to this collection through the use of MyEntity.Others.Add(entity). This is because I may want some validation code to be performed before adding my entity to the collection. I'd do this by providing a method on MyEntity like this:
public void AddOther(OtherEntity other)
{
// perform validation code here
this.Others.Add(other);
}
I've tested a few things so far, and what I've eventually arrived at is something like this. I create a private collection on my entity and expose a public ReadOnlyCollection<T> so MyEntity looks like this:
public class MyEntity
{
private readonly ICollection<OtherEntity> _others = new Collection<OtherEntity>();
public virtual IEnumerable<OtherEntity>
{
get
{
return _others.AsEnumerable();
}
}
}
This seems to be what I'm looking for and my unit tests pass fine, but I haven't yet started to do any integration testing so I'm wondering:
Is there a better way to achieve what I'm looking for?
What are the implications I'll face if I decide to go down this route (if feasible)?
Thanks always for any and all help.
Edit 1 I've changed from using a ReadOnlyCollection to IEnumerable and am using return _others.AsEnumerable(); as my getter. Again unit tests pass fine, but I'm unsure of the problems I'll face during integration and EF starts building these collections with related entities.
Edit 2 So, I decided to try out suggestions of creating a derived collection (call it ValidatableCollection) implementing ICollection where my .Add() method would perform validation on the entity provided before adding it to the internal collection. Unfortunately, Entity Framework invokes this method when building the navigation property - so it's not really suitable.
I would create collection class exactly for this purpose:
OtherEntityCollection : Collection<OtherEntity>
{
protected override void InsertItem(int index, OtherEntity item)
{
// do your validation here
base.InsertItem(index, item);
}
// other overrides
}
This will make much more rigid, because there will be no way to bypass this validation. You can check more complex example in documentation.
One thing I'm not sure is how to make EF create this concrete type when it materializes data from database. But it is probably doable as seen here.
Edit:
If you want to keep the validation inside the entity, you could make it generic through custom interface, that the entity would implement and your generic collection, that would call this interface.
As for problems with EF, I think the biggest problem would be that when EF rematerializes the collection, it calls Add for each item. This then calls the validation, even when the item is not "added" as business rule, but as an infrastructure behavior. This might result in weird behavior and bugs.
I suggest returning to ReadOnlyCollection<T>. I've used it in similar scenarios in the past, and I've had no problems.
Additionally, the AsEnumerable() approach will not work, as it only changes the type of the reference, it does not generate a new, independent object, which means that this
MyEntity m = new MyEntity();
Console.WriteLine(m.Others.Count()); //0
(m.Others as Collection<OtherEntity>).Add(new OtherEntity{ID = 1});
Console.WriteLine(m.Others.Count()); //1
will successfully insert in your private collection.
You shouldn't use AsEnumerable() on HashSet, because collection can be easily modified by casting it to ICollection<OtherEntity>
var values = new MyEntity().Entities;
((ICollection<OtherEntity>)values).Add(new OtherEntity());
Try to return copy of a list like
return new ReadOnlyCollection<OtherEntity>(_others.ToList()).AsEnumerable();
this makes sure that users will recieve exception if they will try to modify it. You can expose ReadOnlyCollection as return type enstead of IEnumerable for clarity and convenience of users. In .NET 4.5 a new interface was added IReadOnlyCollection.
You won't have big integration issues except some component depend on List mutation. If users will call ToList or ToArray, they will return a copy
You have two options here:
1) The way you are currently using: expose the collection as a ReadOnlyCollection<OtherEntity> and add methods in the MyEntity class to modify that collection. This is perfectly fine, but take into account that you are adding the validation logic for a collection of OtherEntity in a class that just uses that collection, so if you use collections of OtherEntity elsewhere in the project, you will need probably need to replicate the validation code, and that's a code smell (DRY) :P
2) To solve that, the best way is to create a custom OtherEntityCollection class implementing ICollection<OtherEntity> so you can add the validation logic there. It's really simple because you can create a simple OtherEntityCollection object that contains a List<OtherEntity> instance which really implements the collection operations, so you just need to validate the insertions:.
Edit: If you need custom validation for multiple entities you should create a custom collection which receives some other object that perform that validation. I've modified the example below, but it shouldn't be difficult to create a generic class:
class OtherEntityCollection : ICollection<OtherEntity>
{
OtherEntityCollection(Predicate<OtherEntity> validation)
{
_validator = validator;
}
private List<OtherEntity> _list = new List<OtherEntity>();
private Predicate<OtherEntity> _validator;
public override void Add(OtherEntity entity)
{
// Validation logic
if(_validator(entity))
_list.Add(entity);
}
}
EF can't map property without setter. or even private set { } requires some configuration. keep models as POCO, Plain-Old like DTO
the common approach is to create separated service layer that contain validation logic against your Model before save.
for sample..
public void AddOtherToMyEntity(MyEntity myEntity, OtherEntity otherEntity)
{
if(myService.Validate(otherEntity)
{
myEntity.Others.Add(otherEntity);
}
//else ...
}
ps. You could prevent compiler to do somethings but not other coders. Just made your code explicitly says "don't modify Entity Collection directly, until it passed validation"
Finally have a suitable working solution, here's what I did. I'll change MyEntity and OtherEntity to something more readable, like Teacher and Student where I want to stop a teacher teaching more students than they can handle.
First, I created an interface for all entities that I intend to validate in this way called IValidatableEntity that looks like this:
public interface IValidatableEntity
{
void Validate();
}
Then I implement this interface on my Student because I'm validating this entity when adding to the collection of Teacher.
public class Student : IValidatableEntity
{
public virtual Teacher Teacher { get; set; }
public void Validate()
{
if (this.Teacher.Students.Count() > this.Teacher.MaxStudents)
{
throw new CustomException("Too many students!");
}
}
}
Now onto how I invoke validate. I override .SaveChanges() on my entity context to get a list of all entities added and for each invoke validate - if it fails I simply set its state to detached to prevent it being added to the collection. Because I'm using exceptions (something I'm still unsure of at this point) as my error messages, I throw them out to preserve the stack trace.
public override int SaveChanges()
{
foreach (var entry in ChangeTracker.Entries())
{
if (entry.State == System.Data.EntityState.Added)
{
if (entry.Entity is IValidatableEntity)
{
try
{
(entry.Entity as IValidatableEntity).Validate();
}
catch
{
entry.State = System.Data.EntityState.Detached;
throw; // preserve the stack trace
}
}
}
}
return base.SaveChanges();
}
This means I keep my validation code nicely tucked away within my entity which will make my life a whole lot easier when mocking my POCOs during unit testing.

Categories

Resources