Domain Model with Nhibernate design issue - c#

I´m trying to get started in the “DDD with C#” world.
I use NHibernate as my ORM tool, thus trying to develop a PI(Persistence Ignorance) model.
However, in some of my entities (which are being represented as POCOS) I have business rules in the setters of my properties.
For example, I have a “User” entity which have a flag that indicates if this user is blocked or not, when this flag is true a second field called “Block Date”
must be automatically filled whith the current date.
Everything seems very clear and simple, but the problem arises in the moment that I´m recovering users that has already persisted in the database, even though
the blocked users will have their “Blocked Dates” update to the current date, according whit this logic.
Initially I thought in a second flag “isLoaded” that would indicates that the object is being hydrated by NHibernate and then this logic wouldn´t be launched,
however this didn´t seem like PI. Any suggestion on how to improve this?

You can define field access strategy in your mapping for the IsBlocked property. Basically, you would say to NHibernate to use underlying private field (_isBlocked) instead of property and hence, your setter logic in IsBlocked property won't be executed.
This SO question has a good answer on access strategies.
Official NHibernate documentation.
If you are using Fluent NHibernate for mapping, this is how you could define it:
Map(x => x.IsBlocked).Access.CamelCaseField(Prefix.Underscore);

In addition to Miroslavs solution for the NHibernate problem, I'd really recommend moving away from putting logic behind property setters, especially when other fields need to be changed.
public void Block()
{
_isBlocked = true;
_blockedDate = DateTime.Now;
}
See answers to this question for why.

Related

Modifying Entity Framework Entities from Multiple Threads

I have a UI thread which enables the user to set certain properties of an entity.
I also have worker threads which will automatically modify properties of an entity that, importantly, the user does not have access to.
Would it be safe to have different DbContexts per thread and just depend on my programming to always avoid modifying the same property and then attempting to SaveChanges() on a context which has the same entity modified in different ways?
Or is there a safer way of doing this, i.e. a way in which it will be possible for a programmer to some day change the code such that the same property is modified from two different contexts safely? Or is this latter situation simply one where the programmer has to be careful/refactor around?
Theoretical part
There are three ways to resolve the concurrency issues in the multi-threading environment:
pessimistic, this can easily be done with locks for an item being edited - no one else can edit the item already being edited. This is very hard to implement approach, and this way is quite bad from performance view - all the editing threads are waiting for a single writer, and just wasting the system resources.
optimistic, this is default way to resolve the issues. The main idea is that you continue the operation until you have a success. There are a lot of algorithm already introduced, I encourage you to read whole wiki-article and, may be, some additional references and/or books on theme.
semi-optimistic, this is a hybrid approach, this way is being used if you need to lock some operations, but not all.
Practice part
Entity framework authors encourage you to use the optimistic way in your app. The simple use-case is to add RowVersion or similar-named property to your model, and catch the DBUpdatedException during the UPDATE.
You can use the Code-First solution, like this:
[Timestamp]
public byte[] RowVersion { get; set; }
or Database-First solution (add column with database editor):
After that, your code for a simple case will be like:
using (var context = new SchoolDBEntities())
{
try
{
context.Entry(student1WithUser2).State = EntityState.Modified;
context.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
Console.WriteLine("Optimistic Concurrency exception occured");
}
}
As I understood, you have to examine some properties of your data source, so I suggest you to read a great article regarding such use-cases (it is about an MVC-application, but I'm sure that you can manage out the main idea).
You can also find several articles regarding concurrency in Entity Framework on MSDN:
Optimistic Concurrency Patterns
Resolving optimistic concurrency exceptions with Reload (database wins)
Resolving optimistic concurrency exceptions as client wins
Custom resolution of optimistic concurrency exceptions
Custom resolution of optimistic concurrency exceptions using objects
Working with Property Values
Getting and setting the current or original value of an individual property
Getting and setting the current value of an unmapped property
Checking whether a property is marked as modified
Marking a property as modified
Reading current, original, and database values for all properties of an entity
Setting current or original values from another object
Setting current or original values from a dictionary
Setting current or original values from a dictionary using Property
Creating a cloned object containing current, original, or database values
Getting and setting the current or original values of complex properties
Using DbPropertyValues to access complex properties
As you can see, this situation relies completely on a developer side, and you have a great amount of patterns you may choose to resolve you concurrent issues by yourself.

DAL update specific field

I am designing a DAL.dll for a web application. The Scenario is that on the web user gets the entity and modifies some fields and click save. My problem is that how to make sure only the modifield field to be saved.
For Example, an entity:
public class POCO{
public int POCOID {get;set;}
public string StringField {get;set;}
public int IntField {get;set;}
}
and my update interface
//rows affected
int update (POCO entity);
When only the IntField is modified, because StringField is null, so I can ignore it. However, when only the StringField is modifield, because IntField is 0 - default(int), I cannot determine if it should be ignored or not.
Some limitations:
1. stateless, no session. so cannot use "get and update", context, etc.
2. to be consistent to data model, cannot use nullable "int?"
Just a tip, if negtive number is not allow in your business requirement, you can use -1 to indicate this value does not apply.
I don't really understand how you want to work stateless, but update only changed properties. It will never work when stateless, since you will need a before-after comparison, or anything else to track changes (like events on property setters). Special "virgin" values are not a good solution, since I think your user wants to see the actual IntField value.
Also make your database consistent with your application data - if you have standard, not-nullable int values, make the DB column int not null default 0! It is really a pain to have a database value which can't be represented by the program, so that the software "magically" turns DB null into 0. If you have a not-nullable int in your application, you can't distinguish between DB null and zero, or you have to add a property like bool IsIntFieldNull (no good!).
To reference a common Object-relational mapper, NHibernate: it has an option called "dynamic-update" where only changed properties/columns are updated. This requires, however, a before-after check and stateful sessions, and there's debate on whether it helps performance, since sending the same DB query every time (with different parameter values) is better than sending multiple different queries - opposed to unneccessary updates and network load. By default, NHibernate updates the whole row, after checking if any change has been done. If you only have ID, StringField and IntField, dynamic-update instead of full-row update might in fact be a good solution.
Mapping nullable DB columns to not-nullable application data types, such as int, is a common mistake when implementing NHibernate, since it creates self-changing DAL objects.
However, when working with ORM or writing your own DAL, make sure you have proper database knowledge!
Options
Many ORMs (Object-relational mapping) provide this type of functionality. You define your object to work with say "Entity Framework" or "NHibernate". These ORM's take care of reading and writing to the database. Internally, they have their own mechanisms to keep track of what has been modified.
Look into Delta<\T> (right now it's an ODATA thing, so it may not be useful to use, but you can learn from it)
Make your own. Have some type of base class that all your other objects inherit from, and somehow when you set fields it records those somewhere else.
I highly recommend not relying on null or magic numbers (-1) to keep track of this. You will create a nightmare for yourself.

When should I update a database to reflect property changes?

I am new to WPF and I am building a small app with Linq To Entities (and SQLite database).
I just would like to know, where do I have to call my methods in order to update the database, when a property has changed ?
I would say in the property in ViewModel like this :
public string FirstName
{
get
{
return this.person.FirstName;
}
set
{
this.person.FirstName = value;
OnPropertyChanged("FirstName");
this.person.updateFirstname(value);
}
}
I am not sure if this is the best solution...
The problem of when to save to the database gives rise to the Unit of Work pattern. Linq-to-Entities has a reasonable implementation of this with the ObjectContext, where data is queued up in the context and then saved to the database when the logical unit of work is complete.
In your example, you are already setting the property on the L2E entity, Person, which is likely connected to the context. When you call ObjectContext.SaveChanges, this will be saved without the need for the updateFirstname method.
The thing you have to decide is when to call ObjectContext.SaveChanges (and thus end the unit of work), and doing this when the user explicitly saves or when the form is closed (optionally propmting for the user to commit or discard changes) is a reasonable approach here. To implement this, your viewmodels reference the ObjectContext and can call the SaveChanges method when the user action (usually modeled with a WPF ICommand published by the viewmodel and bound to the view) is executed.
You should concentrate your updates around unit-of-work rather than around individual fields. If your database is properly normalized each row will represent an entity and should be treated as such, updates to an entity should keep an entity in "valid" state. In your scenario if you update person's first name with intention of also updating last name if the app or server blows up your person record will be invalid.
In terms of MVVM, I usually either piggyback on grid's "update entire row at once" strategy and route that event into viewmodel or I just give them a save button :)
It is best to inject a service Interface into your ViewModel constructor and use some type of service to update the database.
This way you end up with loosely coupled system and your ViewModel stays agnostic of your Data Access Layer as it should...

NHibernate Mapping Sanity Checks

Currently our new database design is changing rapidly and I don't always have time to keep up to date with the latest changes being made. Therefore I would like to create some basic integration tests that are basically sanity checks on my mappings against the database.
Here are a few of the things I'd like to accomplish in these tests:
Detect columns I have not defined in my mapping but exist in the database
Detect columns I have mapped but do NOT exist in the database
Detect columns that I have mapped where the data types between the database and my business objects no longer jive with each other
Detect column name changes between database and my mapping
I found the following article by Ayende but I just want to see what other people out there are doing to handle these sort of things. Basically I'm looking for simplified tests that cover a lot of my mappings but do not require me to write seperate queries for every business object in my mappings.
I'm happy with this test, that comes from the Ayende proposed one:
[Test]
public void PerformSanityCheck()
{
foreach (var s in NHHelper.Instance.GetConfig().ClassMappings)
{
Console.WriteLine(" *************** " + s.MappedClass.Name);
NHHelper.Instance.CurrentSession.CreateQuery(string.Format("from {0} e", s.MappedClass.Name))
.SetFirstResult(0).SetMaxResults(50).List();
}
}
I'm using plain old query since this version comes from a very old project and I'm to lazy to update with QueryOver or Linq2NH or something else...
It basically ping all mapped entities configured and grasp some data too in order to see that all is ok. It does not care if some field exists in the table but not on the mapping, that can generate problem in persistence if not nullable.
I'm aware that Fabio Maulo has something eventually more accurate.
As a personal consideration, if you are thinking on improvement, I would try to implement such a strategy: since mapping are browsable by API, look for any explicit / implicit table declaration in the map, and ping it with the database using the standard schema helperclasses you have inside NH ( they eventually uses the ADO.NET schema classes, but they insulate all the configuration stuff we already did in NH itself) By playng a little with naming strategy we can achieve a one by one table field check list. Another improvement can be done by, in case of unmatching field, looking for a candidate by applying Levensthein Distance to all the available names and choosing one if some threshold requisites are satisfied. This of course is useless in class first scenarios when the DB schema are generated by NH itself.
I use this one too:
Verifying NHibernate Entities Contain Only Virtual Members

Changing Entities in the EntityFramework

I have the following scenario:
Entities are loaded from the database.
One of them is presented to the user in a Form (a WPF UserControl) where the user can edit properties of that entity.
The user can decide to apply the changes to the entity or to cancel the editing.
How would I implement something like this with the EntityFramework?
My problem is that, when I bind the UI directly to the Properties of the Entity, every change is instantanously applied to the entity. I want to delay that to the moment where the user presses OK and the entity is validated successfully.
I thought about loading the Entities with NoTracking and calling ApplyPropertyChanges after the detached entity has been validated, but I'm not entirely sure about the correct way to do that. The docu of the EntityFramework at MSDN is very sparse.
Another way I could think of is to Refresh the entity with StoreWins, but I don't like resetting the changes at Cancel instead of applying changes at Ok.
Has anyone a good tutorial or sample?
One options is what you said do a no-tracking query.
ctx.Customers.MergeOption = MergeOption.NoTracking;
var customer = ctx.Customers.First(c => c.ID == 232);
Then the customer can modify 'customer' as required in memory, and nothing is actually happening in the context.
Now when you want actually make the change you can do this:
// get the value from the database
var original = ctx.Customers.First(c => c.ID == customer.ID);
// copy values from the changed entity onto the original.
ctx.ApplyPropertyChanges(customer); .
ctx.SaveChanges();
Now if you are uncomfortable with the query either for performance or concurrency reasons, you could add a new extension method AttachAsModified(...) to ObjectContext.
that looks something like this:
public static void AttachAsModified<T>(
this ObjectContext ctx,
string entitySet,
T entity)
{
ctx.AttachTo(entitySet, entity);
ObjectStateEntry entry =
ctx.ObjectStateManager.GetObjectStateEntry(entity);
// get all the property names
var propertyNames =
from s in entry.CurrentValues.DataRecordInfo.FieldMetadata
select s.FieldType.Name;
// mark every property as modified
foreach(var propertyName in propertyNames)
{
entry.SetModifiedProperty(propertyName);
}
}
Now you can write code like this:
ctx.Customers.MergeOption = MergeOption.NoTracking;
var customer = ctx.Customers.First();
// make changes to the customer in the form
ctx.AttachAsModified("Customers", customer);
ctx.SaveChanges();
And now you have no concurrency or extranous queries.
The only problem now is dealing with FK properties. You should probably look at my index of tips for help here: http://blogs.msdn.com/alexj/archive/2009/03/26/index-of-tips.aspx
Hope this helps
Alex
I suggest IEditableObject, too, and additionally IDataErrorInfo.
The way i do it is, i basically have a viewmodel for an entity that takes the entity as constructor parameter (basically a wrapper object).
In BeginEdit, i copy the entity properties to my viewmodel, so if i do CancelEdit, the data is only changed in the ViewModel and the original Entity hasn't changed. In EndEdit, i just apply the ViewModel properties to the Entity again, or course only if validation has succeeded.
For validation i use the methods of IDataErrorInfo. I just implement IDataErrorInfo.Error so that it checks each Property name via IDataErrorInfo[string columnName] and concatenates eventual error messages. If it's empty, everything is ok. (not sure if Error is meant to be used that way, but i do it)
If i have other Entities attached to my original Entity, such as Customer.Orders, i create them as nested ViewModels in the original Entity's ViewModel. The original ViewModel calls it's subModels' Begin-,Cancel-,EndEdit / Error methods in it's own implementations of those methods then.
It's a bit more work, but i think it's worth it because between BeginEdit and EndEdit, you can be pretty sure that nothing changes without you noticing it. And having a code snippet for INotifyPropertyChanged-enabled properties helps a lot, too.
The normal way of doing this is binding to something that implements IEditableObject. If and how that fits in with the entity framework, I'm not sure.

Categories

Resources