I have a set of entities that I would like to persist via the repository pattern.
Vanilla SQL is pretty straight forward, write some methods that have queries that take/return the entities.
Azure table storage is also pretty straight forward, except that most of the implementations I have seen want the entities to be decended from some common Azure base class. (TableServiceEntity etc)
EF works as well, but also wants to own a bit more of the entities.
Is there a good way to abstract away both the SQL and Azure table stuff so that the entities can be persisted either way?
Bidirectional support is not really needed, we are just going to have two different deployment types that need to be supported.
I would like the models to be as agnostic as possible of the repository they are being persisted in, with as few dependancies (none?!) if possible.
This is doable. I've helped architect this for a client on a decently large scale.
1) Do not inherit from TableServiceEntity but instead implement the following attribute on your entities:
[DataServiceKey(new string[] { "PartitionKey", "RowKey" }), Serializable]
Also, implement some sort of an interface on your entities that provides PartitionKey,RowKey, and Timestamp to your entities.
public interface ITableEntity
{
string PartitionKey { get; set; }
string RowKey { get; set; }
DateTime Timestamp { get; set; }
}
At least this approach will allow you to have your own inheritance strategy for your own entities and not be restricted due to lack of multi-inheritance. Try to have PartitionKey and RowKey simply provide a pass-through to the real key properties instead of duplicating the keys.
public string PartitionKey
{
get
{
return this.Id;
}
set
{
this.Id = value;
}
}
2) Do realize that you will have two types of repositories in your system: relational-specific and ATS-specific.
3) You can generate your entities via EDMX and use partial classes to inject them with ITableEntity and DataServiceKey attribute
4) At some point you will need your ATS-specific repositories to do some transformations of your entities for persistence's sake, because of the way you'll be saving data into ATS is not the way you'll want it modeled in your domain (this especially relates to hierarchical or relational data)
HTH
Related
I've been struggling around a DDD-related issue with Specifications and I've read much into DDD and specifications and repositories.
However, there is an issue if trying to combine all 3 of these without breaking the domain-driven design. It boils down to how to apply filters with performance in mind.
First a few obvious facts:
Repositories to got DataAccess/Infrastructure Layer
Domain Models represent Business Logic and go to the Domain layer
Data Access Models represent the Persistence layer and go to the Persistence/Infrastructure/DataAccess layer
Business Logic goes to Domain Layer
Specifications are Business Logic, so they belong to the Domain layer too.
In all these examples, an ORM Framework and SQL Server is used inside the Repository
Persistance Models may not leak into Domain Layer
So far, so easy. The problem arises when/if we try to apply Specifications to the Repository and not breaking the DDD pattern or having performance issues.
The possible ways to apply Specifications:
1) Classic way: Specifications using Domain Model in Domain Layer
Apply the traditional Specification Pattern, with a IsSatisfiedBy method, returning a bool and Composite Specifications to combine multiple Specifications.
This let us keep specifications in Domain Layer, but...
It has to work with Domain Models, while the repository uses Persistence Models which represent the data structure of the persistence layer. This one is easy to fix with the usage of mappers such as AutoMapper.
However, the problem which can't be solved: All the specifications would have to be performed in memory. In a big table/database this means a huge impact if you have to iterate through ALL Entities only to filter out the one which meets your specifications
2) Specifications using Persistence Model
This is similar to 1), but using Persistence Models in the specification. This allows direct use of the Specification as part of our .Where predicate which will be translated into a query (i.e. TSQL) and the filtering will be performed on the Persistence storage (i.e. SQL Server).
While this gives us good performance, it clearly violates the DDD pattern. Our Persistence model leaks into the Domain layer, making the Domain Layer depend on the Persistence Layer instead of the other way around.
3) Like 2), but make Specifications Part of the Persistence Layer
This doesn't work, because Domain Layer needs to reference the Specifications. It would still depend on the persistence layer.
We would have business logic inside the Persistence layer. Which also violates the DDD pattern
4) Like 3, but use abstract the Specifications as Interfaces
We would have Specification interfaces in our Domain layer, our concrete implementations of the Specifications in the Persistence Layer. Now our Domain Layer would only interact with the interfaces and not depend on the Persistence layer.
This still violates #2 from 3). We would have business logic in the persistence layer, which is bad.
5) Translate the Expression Tree from Domain Model into Persistence Model
This certainly solves the problem, but it's a non-trivial task but it would keep the Specifications inside our Domain Layer while still benefiting from SQL optimization because the Specifications becomes part of the Repositories Where clause and translates into TSQL
I tried going this approach and there are several issues (from the implementation side):
We would need to know the Configuration from the Mapper (if we use one) or keep our own mapping system. This can be partly done (reading Mapper configuration) with i.e. AutoMapper, but further issues exist
It's acceptable for one where one Property of Model A maps to one Property of Model B. It becomes more difficult if the types are different (i.e. due to persistence types, for example, Enums being saved as strings or key/value pairs in another table and we need to do conversions inside the resolver.
It gets pretty complicated if multiple fields get mapped into one destination field. I believe this is non an issue for Domain Model -> Persistence Model mappings
6) Query Builder like API
The last one is making some kind of query API which is passed into the specification and from whom the Repository/Persistence layer would generate an Expression Tree to be passed to .Where clause and which uses an Interface to declare all filterable fields.
I did a few attempts in that direction too but wasn't too happy about the results. Something like
public interface IQuery<T>
{
IQuery<T> Where(Expression<Func<T, T>> predicate);
}
public interface IQueryFilter<TFilter>
{
TFilter And(TFilter other);
TFilter Or(TFilter other);
TFilter Not(TFilter other);
}
public interface IQueryField<TSource, IQueryFilter>
{
IQueryFilter Equal(TSource other);
IQueryFilter GreaterThan(TSource other);
IQueryFilter Greater(TSource other);
IQueryFilter LesserThan(TSource other);
IQueryFilter Lesser(TSource other);
}
public interface IPersonQueryFilter : IQueryFilter<IPersonQueryFilter>
{
IQueryField<int, IPersonQueryFilter> ID { get; }
IQueryField<string, IPersonQueryFilter> Name { get; }
IQueryField<int, IPersonQueryFilter> Age { get; }
}
and in the specification, we would pass an IQuery<IPersonQueryFilter> query to the specifications constructor and then apply the specifications to it when using or combining it.
IQuery<IGridQueryFilter> query = null;
query.Where(f => f.Name.Equal("Bob") );
I don't like this approach much, as it makes handling complex specifications somewhat hard (like and or if chaining) and I don't like the way the And/Or/Not would work, especially creating expression trees from this "API".
I have been looking for weeks all over the Internet read dozens of articles on DDD and Specification, but they always only handle simple cases and don't take the performance into consideration or they violate the DDD pattern.
How do you solve this in a real-world application without doing in-memory filtering or leaking Persistence into Domain Layer??
Are there any frameworks that solve the issues above with one of the two ways (Query Builder like syntax to Expression Trees or an Expression Tree translator)?
I think Specification pattern is not designed for query criteria. Actually, the whole concept of DDD is not, either. Consider CQRS if there are plethora of query requirements.
Specification pattern helps develop ubiquitous language, I think it's like kind of a DSL. It declares what to do rather than how to do it. For example, in a ordering context, orders are considered as overdue if it was placed but not paid within 30 minutes. With Specification pattern, your team can talk with a short but unique term: OverdueOrderSpecification. Imagine the discussion below:
case -1
Business people: I want to find out all overdue orders and ...
Developer: I can do that, it is easy to find all satisfying orders with an overdue order specification and..
case -2
Business people: I want to find out all orders which were placed before 30 minutes and still unpaid...
Developer: I can do that, it is easy to filter order from tbl_order where placed_at is less that 30minutes before sysdate....
Which one do you prefer?
Usually, we need a DSL handler to parse the dsl, in this case, it may be in the persistence adapter, translates the specification to a query criteria. This dependence (infrastrructure.persistence => domain) does not violates the architecture principal.
class OrderMonitorApplication {
public void alarm() {
// The specification pattern keeps the overdue order ubiquitous language in domain
List<Order> overdueOrders = orderRepository.findBy(new OverdueSpecification());
for (Order order: overdueOrders) {
//notify admin
}
}
}
class HibernateOrderRepository implements orderRepository {
public List<Order> findBy(OrderSpecification spec) {
criteria.le("whenPlaced", spec.placedBefore())//returns sysdate - 30
criteria.eq("status", spec.status());//returns WAIT_PAYMENT
return ...
}
}
Once I implemented Specification but...
It was based on LINQ and IQueryable.
It used single unified Repository (but as for me it's not bad and I think that it's main reason to use Specification).
It used single model for domain and persistant needs (which I think to be bad).
Repository:
public interface IRepository<TEntity> where TEntity : Entity, IAggregateRoot
{
TEntity Get<TKey>(TKey id);
TEntity TryGet<TKey>(TKey id);
void DeleteByKey<TKey>(TKey id);
void Delete(TEntity entity);
void Delete(IEnumerable<TEntity> entities);
IEnumerable<TEntity> List(FilterSpecification<TEntity> specification);
TEntity Single(FilterSpecification<TEntity> specification);
TEntity First(FilterSpecification<TEntity> specification);
TResult Compute<TResult>(ComputationSpecification<TEntity, TResult> specification);
IEnumerable<TEntity> ListAll();
//and some other methods
}
Filter specification:
public abstract class FilterSpecification<TAggregateRoot> where TAggregateRoot : Entity, IAggregateRoot
{
public abstract IQueryable<TAggregateRoot> Filter(IQueryable<TAggregateRoot> aggregateRoots);
public static FilterSpecification<TAggregateRoot> CreateByPredicate(Expression<Func<TAggregateRoot, bool>> predicate)
{
return new PredicateFilterSpecification<TAggregateRoot>(predicate);
}
public static FilterSpecification<TAggregateRoot> operator &(FilterSpecification<TAggregateRoot> op1, FilterSpecification<TAggregateRoot> op2)
{
return new CompositeFilterSpecification<TAggregateRoot>(op1, op2);
}
public static FilterSpecification<TAggregateRoot> CreateDummy()
{
return new DummyFilterSpecification<TAggregateRoot>();
}
}
public class CompositeFilterSpecification<TAggregateRoot> : FilterSpecification<TAggregateRoot> where TAggregateRoot : Entity, IAggregateRoot
{
private readonly FilterSpecification<TAggregateRoot> _firstOperand;
private readonly FilterSpecification<TAggregateRoot> _secondOperand;
public CompositeFilterSpecification(FilterSpecification<TAggregateRoot> firstOperand, FilterSpecification<TAggregateRoot> secondOperand)
{
_firstOperand = firstOperand;
_secondOperand = secondOperand;
}
public override IQueryable<TAggregateRoot> Filter(IQueryable<TAggregateRoot> aggregateRoots)
{
var operand1Results = _firstOperand.Filter(aggregateRoots);
return _secondOperand.Filter(operand1Results);
}
}
public class PredicateFilterSpecification<TAggregateRoot> : FilterSpecification<TAggregateRoot> where TAggregateRoot : Entity, IAggregateRoot
{
private readonly Expression<Func<TAggregateRoot, bool>> _predicate;
public PredicateFilterSpecification(Expression<Func<TAggregateRoot, bool>> predicate)
{
_predicate = predicate;
}
public override IQueryable<TAggregateRoot> Filter(IQueryable<TAggregateRoot> aggregateRoots)
{
return aggregateRoots.Where(_predicate);
}
}
Another kind of specification:
public abstract class ComputationSpecification<TAggregateRoot, TResult> where TAggregateRoot : Entity, IAggregateRoot
{
public abstract TResult Compute(IQueryable<TAggregateRoot> aggregateRoots);
public static CompositeComputationSpecification<TAggregateRoot, TResult> operator &(FilterSpecification<TAggregateRoot> op1, ComputationSpecification<TAggregateRoot, TResult> op2)
{
return new CompositeComputationSpecification<TAggregateRoot, TResult>(op1, op2);
}
}
and usages:
OrderRepository.Compute(new MaxInvoiceNumberComputationSpecification()) + 1
PlaceRepository.Single(FilterSpecification<Place>.CreateByPredicate(p => p.Name == placeName));
UnitRepository.Compute(new UnitsAreAvailableForPickingFilterSpecification() & new CheckStockContainsEnoughUnitsOfGivenProductComputatonSpecification(count, product));
Custom implementations may look like
public class CheckUnitsOfGivenProductExistOnPlaceComputationSpecification : ComputationSpecification<Unit, bool>
{
private readonly Product _product;
private readonly Place _place;
public CheckUnitsOfGivenProductExistOnPlaceComputationSpecification(
Place place,
Product product)
{
_place = place;
_product = product;
}
public override bool Compute(IQueryable<Unit> aggregateRoots)
{
return aggregateRoots.Any(unit => unit.Product == _product && unit.Place == _place);
}
}
Finally, I'm forced to tell that simple Specficiation implementation fits bad according to DDD. You have done great research in this area and it's unlikely that someone proposes something new :). Also, take a look at http://www.sapiensworks.com/blog/ blog.
I´m late for the party, bug here are my 2 cents...
I did also struggle implementing the specification pattern for exactly the same reasons you described above. If you abandon the requirement for a separate model (Persistence / Domain) then your problem is greatly simplified. you could add another method to the specification to generate the expression tree for the ORM:
public interface ISpecification<T>
{
bool IsSpecifiedBy(T item);
Expression<Func<T, bool>> GetPredicate()
}
There is a post from Valdmir Khorikov describing how to do that in detail.
However, I really don´t like have a single model. Like you I find that Peristence model should be kept in the infrastructure layer to not contaminate your domain because of ORM limitations.
Eventually I came up with a solution using a visitor to translate the the domain model to an expression tree of the persistence model.
I recently wrote a series of posts where I explain
How to create a Generic specification in C#
What is a Visitor Design Pattern and how to make it generic.
And my take on how to implement specification pattern in entity framework
The end result becomes very simple to use actually, you´ll need to make the specification Visitable...
public interface IProductSpecification
{
bool IsSpecifiedBy(Product item);
TResult Accept<TResult>(IProductSpecificationVisitor<TResult> visitor);
}
Create a SpecificationVisitor to translate the specification to an expression:
public class ProductEFExpressionVisitor : IProductSpecificationVisitor<Expression<Func<EFProduct, bool>>>
{
public Expression<Func<EFProduct, bool>> Visit (ProductMatchesCategory spec)
{
var categoryName = spec.Category.CategoryName;
return ef => ef.Category == categoryName;
}
//other specification-specific visit methods
}
There is just some tweeking that needs to be done if you want to create a generic spefication. It´s all detailed in the posts referenced above.
I have been looking for weeks all over the Internet, read dozens of
articles on DDD and Specification, but they always only handle simple
cases and don't take the performance into consideration or they
violate DDD pattern.
Someone will correct me if I'm wrong, but it seems to me that the concept of a "Persistence Model" didn't appear until very recently in the DDD space (by the way, where did you read about it ?). I'm not sure it's described in the original blue book.
I personally don't see many advantages to it. My view is that you have a persisted (usually) relational model in your database and an in-memory domain model in your application. The gap between the two is bridged by an action, not a model. This action can be performed by an ORM. I have yet to be sold on the fact that a "Persistence object model" really makes sense semantically, let alone is mandatory to respect DDD principles (*).
Now there's the CQRS approach where you have a separate Read Model, but this is a totally different animal and I wouldn't see Specifications acting on Read Model objects instead of Entities as a DDD violation in this case. Specification is after all a very general pattern that nothing in DDD fundamentally restricts to Entities.
(*) Edit : Automapper creator Jimmy Bogard seems to find it overcomplicated as well - See How do I use automapper to map many-to-many relationships?
In my domain I have something called Project which basically holds a lot of simple configuration propeties that describe what should happen when the project gets executed. When the Project gets executed it produces a huge amount of LogEntries. In my application I need to analyse these log entries for a given Project, so I need to be able to partially successively load a portion (time frame) of log entries from the database (Oracle). How would you model this relationship as DB tables and as objects?
I could have a Project table and ProjectLog table and have a foreign key to the primary key of Project and do the "same" thing at object level have class Project and a property
IEnumerable<LogEntry> LogEntries { get; }
and have NHibernate do all the mapping. But how would I design my ProjectRepository in this case? I could have a methods
void FillLog(Project projectToFill, DateTime start, DateTime end);
How can I tell NHibernate that it should not load the LogEntries until someone calls this method and how would I make NHibernate to load a specifc timeframe within that method?
I am pretty new to ORM, maybe that design is not optimal for NHibernate or in general? Maybe I shoul design it differently?
Instead of having a Project entity as an aggregate root, why not move the reference around and let LogEntry have a Product property and also act as an aggregate root.
public class LogEntry
{
public virtual Product Product { get; set; }
// ...other properties
}
public class Product
{
// remove the LogEntries property from Product
// public virtual IList<LogEntry> LogEntries { get; set; }
}
Now, since both of those entities are aggregate roots, you would have two different repositories: ProductRepository and LogEntryRepository. LogEntryRepository could have a method GetByProductAndTime:
IEnumerable<LogEntry> GetByProductAndTime(Project project, DateTime start, DateTime end);
The 'correct' way of loading partial / filtered / criteria-based lists under NHibernate is to use queries. There is lazy="extra" but it doesn't do what you want.
As you've already noted, that breaks the DDD model of Root Aggregate -> Children. I struggled with just this problem for an absolute age, because first of all I hated having what amounted to persistence concerns polluting my domain model, and I could never get the API surface to look 'right'. Filter methods on the owning entity class work but are far from pretty.
In the end I settled for extending my entity base class (all my entities inherit from it, which I know is slightly unfashionable these days but it does at least let me do this sort of thing consistently) with a protected method called Query<T>() that takes a LINQ expression defining the relationship and, under the hood in the repository, calls LINQ-to-NH and returns an IQueryable<T> that you can then query into as you require. I can then facade that call beneath a regular property.
The base class does this:
protected virtual IQueryable<TCollection> Query<TCollection>(Expression<Func<TCollection, bool>> selector)
where TCollection : class, IPersistent
{
return Repository.For<TCollection>().Where(selector);
}
(I should note here that my Repository implementation implements IQueryable<T> directly and then delegates the work down to the NH Session.Query<T>())
And the facading works like this:
public virtual IQueryable<Form> Forms
{
get
{
return Query<Form>(x => x.Account == this);
}
}
This defines the list relationship between Account and Form as the inverse of the actual mapped relationship (Form -> Account).
For 'infinite' collections - where there is a potentially unbounded number of objects in the set - this works OK, but it means you can't map the relationship directly in NHibernate and therefore can't use the property directly in NH queries, only indirectly.
What we really need is a replacement for NHibernate's generic bag, list and set implementations that knows how to use the LINQ provider to query into lists directly. One has been proposed as a patch (see https://nhibernate.jira.com/browse/NH-2319). As you can see the patch was not finished or accepted and from what I can see the proposer didn't re-package this as an extension - Diego Mijelshon is a user here on SO so perhaps he'll chime in... I have tested out his proposed code as a POC and it does work as advertised, but obviously it's not tested or guaranteed or necessarily complete, it might have side-effects, and without permission to use or publish it you couldn't use it anyway.
Until and unless the NH team get around to writing / accepting a patch that makes this happen, we'll have to keep resorting to workarounds. NH and DDD just have conflicting views of the world, here.
I am using Fluent nHibernate for my persistence layer in an ASP.NET MVC application, and I have come across a bit of a quandry.
I have a situation where I need to use an abstraction to store objects into a collection, in this situation, an interface is the most logical choice if you are looking at a pure C# perspective.
Basically, an object (Item) can have Requirements. A requirement can be many things. In a native C# situation, I would merely accomplish this with the following code.
interface IRequirement
{
// methods and properties neccessary for evaluation
}
class Item
{
virtual int Id { get; set; }
virtual IList<IRequirement> Requirements { get; set; }
}
A crude example. This works fine in native C# - however because the objects have to be stored in a database, it becomes a bit more complicated than that. Each object that implements IRequirement could be a completely different kind of object. Since nHibernate (or any other ORM that I have discovered) cannot really understand how to serialize an interface, I cannot think of, for the life of me, how to approach this scenario. I mean, I understand the problem.
This makes no sense to the database/orm. I understand completely why, too.
class SomeKindOfObject
{
virtual int Id { get; set; }
// ... some other methods relative to this base type
}
class OneRequirement : SomeKindOfObject, IRequirement
{
virtual string Name { get; set; }
// some more methods and properties
}
class AnotherKindOfObject
{
virtual int Id { get; set; }
// ... more methods and properties, different from SomeKindOfObject
}
class AnotherRequirement : AnotherKindOfObject, IRequirement
{
// yet more methods and properties relative to AnotherKindOfObject's intentive hierarchy
}
class OneRequirementMap : ClassMap<OneRequirement>
{
// etc
Table("OneRequirement");
}
class AnotherRequirementMap : ClassMap<AnotherRequirement>
{
//
Table("OtherRequirements");
}
class ItemMap : ClassMap<Item>
{
// ... Now we have a problem.
Map( x => x.Requirements ) // does not compute...
// additional mapping
}
So, does anyone have any ideas? I cannot seem to use generics, either, so making a basic Requirement<T> type seems out. I mean the code works and runs, but the ORM cannot grasp it. I realize what I am asking here is probably impossible, but all I can do is ask.
I would also like to add, I do not have much experience with nHibernate, only Fluent nHibernate, but I have been made aware that both communities are very good and so I am tagging this as both. But my mapping at present is 100% 'fluent'.
Edit
I actually discovered Programming to interfaces while mapping with Fluent NHibernate that touches on this a bit, but I'm still not sure it is applicable to my scenario. Any help is appreciated.
UPDATE (02/02/2011)
I'm adding this update in response to some of the answers posted, as my results are ... a little awkward.
Taking the advice, and doing more research, I've designed a basic interface.
interface IRequirement
{
// ... Same as it always was
}
and now I establish my class mapping..
class IRequirementMap : ClassMap<IRequirement>
{
public IRequirementMap()
{
Id( x => x.Id );
UseUnionSubclassForInheritanceMapping();
Table("Requirements");
}
}
And then I map something that implements it. This is where it gets very freaky.
class ObjectThatImplementsRequirementMap : ClassMap<ObjectThatImplementsRequirement>
{
ObjectThatImplementsRequirementMap()
{
Id(x => x.Id); // Yes, I am base-class mapping it.
// other properties
Table("ObjectImplementingRequirement");
}
}
class AnotherObjectThatHasRequirementMap : ClassMap<AnotherObjectThatHasRequirement>
{
AnotherObjectThatHasRequirementMap ()
{
Id(x => x.Id); // Yes, I am base-class mapping it.
// other properties
Table("AnotheObjectImplementingRequirement");
}
}
This is not what people have suggested, but it was my first approach. Though I did it because I got some very freaky results. Results that really make no sense to me.
It Actually Works... Sort Of
Running the following code yields unanticipated results.
// setup ISession
// setup Transaction
var requirements = new <IRequirement>
{
new ObjectThatImplementsRequirement
{
// properties, etc..
},
new AnotherObjectThatHasRequirement
{
// other properties.
}
}
// add to session.
// commit transaction.
// close writing block.
// setup new session
// setup new transaction
var requireables = session.Query<IRequirable>();
foreach(var requireable in requireables)
Console.WriteLine( requireable.Id );
Now things get freaky. I get the results...
1
1
This makes no sense to me. It shouldn't work. I can even query the individual properties of each object, and they have retained their type. Even if I run the insertion, close the application, then run the retrieval (so as to avoid the possibility of caching), they still have the right types. But the following does not work.
class SomethingThatHasRequireables
{
// ...
public virtual IList<IRequirement> Requirements { get; set; }
}
Trying to add to that collection fails (as I expect it to). Here is why I am confused.
If I can add to the generic IList<IRequirement> in my session, why not in an object?
How is nHibernate understanding the difference between two entities with the same Id,
if they are both mapped as the same kind of object, in one scenario, and not the other?
Can someone explain to me what in the world is going on here?
The suggested approach is to use SubclassMap<T>, however the problem with that is the number of identities, and the size of the table. I am concerned about scalability and performance if multiple objects (up to about 8) are referencing identities from one table. Can someone give me some insight on this one specifically?
Take a look at the chapter Inheritance mapping in the reference documentation. In the chapter Limitations you can see what's possible with which mapping strategy.
You've chose one of the "table per concrete class" strategies, as far as I can see. You may need <one-to-many> with inverse=true or <many-to-any> to map it.
If you want to avoid this, you need to map IRequirement as a base class into a table, then it is possible to have foreign keys to that table. Doing so you turn it into a "table per class-hierarchy" or "table per subclass" mapping. This is of course not possible if another base class is already mapped. E.g. SomeKindOfObject.
Edit: some more information about <one-to-many> with inverse=true and <many-to-any>.
When you use <one-to-many>, the foreign key is actually in the requirement tables pointing back to the Item. This works well so far, NH unions all the requirement tables to find all the items in the list. Inverse is required because it forces you to have a reference from the requirement to the Item, which is used by NH to build the foreign key.
<many-to-any> is even more flexible. It stores the list in an additional link table. This table has three columns:
the foreign key to the Item,
the name of the actual requirement type (.NET type or entity name)
and the primary key of the requirement (which can't be a foreign key, because it could point to different tables).
When NH reads this table, it knows from the type information (and the corresponding requirement mapping) in which other tables the requirements are. This is how any-types work.
That it is actually a many-to-many relation shouldn't bother you, it only means that it stores the relation in an additional table which is technically able to link a requirement to more then one item.
Edit 2: freaky results:
You mapped 3 tables: IRequirement, ObjectThatImplementsRequirement, AnotherObjectThatHasRequirement. They are all completely independent. You are still on "table per concrete class with implicit polymorphism". You just added another table with containing IRequirements, which may also result in some ambiguity when NH tries to find the correct table.
Of course you get 1, 1 as result. The have independent tables and therefore independent ids which both start with 1.
The part that works: NHibernate is able to find all the objects implementing an interface in the whole database when you query for it. Try session.CreateQuery("from object") and you get the whole database.
The part that doesn't work: On the other side, you can't get an object just by id and interface or object. So session.Get<object>(1) doesn't work, because there are many objects with id 1. The same problem is with the list. And there are some more problems there, for instance the fact that with implicit polymorphism, there is no foreign key specified which points from every type implementing IRequirement to the Item.
The any types: This is where the any type mapping comes in. Any types are stored with additional type information in the database and that's done by the <many-to-any> mapping which stores the foreign key and type information in an additional table. With this additional type information NH is able to find the table where the record is stored in.
The freaky results: Consider that NH needs to find both ways, from the object to a single table and from the record to a single class. So be careful when mapping both the interface and the concrete classes independently. It could happen that NH uses one or the other table depending on which way you access the data. This may have been the cause or your freaky results.
The other solution: Using any of the other inheritance mapping strategies, you define a single table where NH can start reading and finding the type.
The Id Scope: If you are using Int32 as id, you can create 1 record each second for 68 years until you run out of ids. If this is not enough, just switch to long, you'll get ... probably more then the database is able to store in the next few thousand years...
Is it a violation of the Persistance igorance to inject a repository interface into a Entity object Like this. By not using a interface I clearly see a problem but when using a interface is there really a problem? Is the code below a good or bad pattern and why?
public class Contact
{
private readonly IAddressRepository _addressRepository;
public Contact(IAddressRepository addressRepository)
{
_addressRepository = addressRepository;
}
private IEnumerable<Address> _addressBook;
public IEnumerable<Address> AddressBook
{
get
{
if(_addressBook == null)
{
_addressBook = _addressRepository.GetAddresses(this.Id);
}
return _addressBook;
}
}
}
It's not exactly a good idea, but it may be ok for some limited scenarios. I'm a little confused by your model, as I have a hard time believing that Address is your aggregate root, and therefore it wouldn't be ordinary to have a full-blown address repository. Based on your example, you probably are actually using a table data gateway or dao rather than a respository.
I prefer to use a data mapper to solve this problem (an ORM or similar solution). Basically, I would take advantage of my ORM to treat address-book as a lazy loaded property of the aggregate root, "Contact". This has the advantage that your changes can be saved as long as the entity is bound to a session.
If I weren't using an ORM, I'd still prefer that the concrete Contact repository implementation set the property of the AddressBook backing store (list, or whatever). I might have the repository set that enumeration to a proxy object that does know about the other data store, and loads it on demand.
You can inject the load function from outside. The new Lazy<T> type in .NET 4.0 comes in handy for that:
public Contact(Lazy<IEnumerable<Address>> addressBook)
{
_addressBook = addressBook;
}
private Lazy<IEnumerable<Address>> _addressBook;
public IEnumerable<Address> AddressBook
{
get { return this._addressBook.Value; }
}
Also note that IEnumerable<T>s might be intrinsically lazy anyhow when you get them from a query provider. But for any other type you can use the Lazy<T>.
Normally when you follow DDD you always operate with the whole aggregate. The repository always returns you a fully loaded aggregate root.
It doesn't make much sense (in DDD at least) to write code as in your example. A Contact aggregate will always contain all the addresses (if it needs them for its behavior, which I doubt to be honest).
So typically ContactRepository supposes to construct you the whole Contact aggregate where Address is an entity or, most likely, a value object inside this aggregate.
Because Address is an entity/value object that belongs to (and therefore managed by) Contact aggregate it will not have its own repository as you are not suppose to manage entities that belong to an aggregate outside this aggregate.
Resume: always load the whole Contact and call its behavior method to do something with its state.
Since its been 2 years since I asked the question and the question somewhat misunderstood I will try to answer it myself.
Rephrased question:
"Should Business entity classes be fully persistance ignorant?"
I think entity classes should be fully persistance ignorant, because you will instanciate them many places in your code base so it will quickly become messy to always have to inject the Repository class into the entity constructor, neither does it look very clean. This becomes even more evident if you are in need of injecting several repositories. Therefore I always use a separate handler/service class to do the persistance jobs for the entities. These classes are instanciated far less frequently and you usually have more control over where and when this happens. Entity classes are kept as lightweight as possible.
I now always have 1 Repository pr aggregate root and if I have need for some extra business logic when entities are fetched from repositories I usually create 1 ServiceClass for the aggregate root.
By taking a tweaked example of the code in the question as it was a bad example I would do it like this now:
Instead of:
public class Contact
{
private readonly IContactRepository _contactRepository;
public Contact(IContactRepository contactRepository)
{
_contactRepository = contactRepository;
}
public void Save()
{
_contactRepository.Save(this);
}
}
I do it like this:
public class Contact
{
}
public class ContactService
{
private readonly IContactRepository _contactRepository;
public ContactService(IContactRepository contactRepository)
{
_contactRepository = contactRepository;
}
public void Save(Contact contact)
{
_contactRepository.Save(contact);
}
}
I have a following mapping:
<set name="People" lazy="true" table="ProjectPeople">
<key column="ProjectId" />
<composite-element class="PersonRole">
<many-to-one name="Person" column="PersonId" cascade="save-update" not-null="true" />
<many-to-one name="Role" column="RoleId" cascade="save-update" not-null="true" />
</composite-element>
</set>
Now, I do not really want to have a separate class for Role in domain, I need only the Role name. However, in DB Roles should still be normalized to a separate table Role (Id, Name).
How do I map it so that People use following PersonRole class?
public class PersonRole {
public virtual Person Person { get; set; }
public virtual string Role { get; set; }
}
Update: added bounty, seems like a question useful not only to me.
You won't actually get the answer you hope for, simply because it is not possible. (N)Hibernate is an Object-Relational-Mapping framework and support three kinds of mapping strategies:
table per class hierarchy
table per subclass
table per concrete class
It also allows you to deviate from this by using formula or sql-insert etc, but as you've found out, these only cause you more pain in the end, are not encouraged by the Hibernate community and are bad for the maintainability of your code.
Solution?
Actually, it is very simple. You do not want to use a class for Role. I assume you mean that you do not want to expose a class of type Role and that you do not want to have to type prObject.Role.Name all the time. Just prObject.Role, which should return a string. You have several options:
Use an inner class in, say, PersonRole, this class can be internal or private. Add a property Role that sets and updates a member field;
Use an internal class. Add a property Role that sets and updates a member field;
Let's examine option 2:
// mapped to table Role, will not be visible to users of your DAL
// class can't be private, it's on namespace level, it can when it's an inner class
internal class Role
{
// typical mapping, need not be internal/protected when class is internal
// cannot be private, because then virtual is not possible
internal virtual int Id { get; private set; }
internal virtual string Name { get; set; }
}
// the composite element
public class PersonRole
{
// mapped properties public
public virtual Person Person { get; set; }
// mapped properties hidden
internal virtual Role dbRole { get; set; }
// not mapped, but convenience property in your DAL
// for clarity, it is actually better to rename to something like RoleName
public string Role /* need not be virtual, but can be */
{
get
{
return this.dbRole.Name;
}
set
{
this.dbRole.Name = value; /* this works and triggers the cascade */
}
}
}
And the mapping can look as expected. Result: you have not violated the one-table-per-class rule (EDIT: asker says that he explicitly wants to violate that rule, and Hib supports it, which is correct), but you've hidden the objects from modification and access by using typical object oriented techniques. All NH features (cascade etc) still work as expected.
(N)Hibernate is all about this type of decisions: how to make a well thought-through and safe abstraction layer to your database without sacrificing clarity, brevity or maintainability or violating OO or ORM rules.
Update (after q. was closed)
Other excellent approaches I use a lot when dealing with this type of issue are:
Create your mappings normally (i.e., one-class-per-table, I know you don't like it, but it's for the best) and use extension methods:
// trivial general example
public static string GetFullName(this Person p)
{
return String.Format("{0} {1}", p.FirstName, p.LastName);
}
// gettor / settor for role.name
public static string GetRoleName(this PersonRole pr)
{
return pr.Role == null ? "" : pr.Role.Name;
}
public static SetRoleName(this PersonRole pr, string name)
{
pr.Role = (pr.Role ?? new Role());
pr.Role.Name = name;
}
Create your mappings normally but use partial classes, which enable you to "decorate" your class any which way you like. The advantage: if you use generated mapping of your tables, you an regenerate as often as you wish. Of course, the partial classes should go in separate files so considering your wish for diminishing "bloat" this probably isn't a good scenario currently.
public partial class PersonRole
{
public string Role {...}
}
Perhaps simplest: just overload ToString() for Role, which makes it suitable for use in String.Format and friends, but of course doesn't make it assignable. By default, each entity class or POCO should have a ToString() overload anyway.
Though it is possible to do this with NHibernate directly, the q. has been closed before I had time to look at it (no ones fault, I just didn't have the time). I'll update if I find the time to do it through Hibernate HBM mapping, even though I don't agree to the approach. It is not good to wrestle with advanced concepts of Hib when the end result is less clear for other programmers and less clear overall (where did that table go? why isn't there a IDao abstraction for that table? See also NHibernate Best Practices and S#arp). However, the exercise is interesting nevertheless.
Considering the comments on "best practices": in typical situations, it shouldn't be only "one class per table", but also one IDaoXXX, one DaoConcreteXXX and one GetDaoXXX for each table, where you use class/interface hierarchy to differentiate between read-only and read/write tables. That's a minimum of four classes/lines of code per table. This is typically auto-generated but gives a very clear access layer (dao) to your data layer (dal). The data layer is best kept as spartan as possible. Nothing of these "best practices" prevent you using extension methods or partial methods for moving Role.Name into Role.
These are best general practices. It's not always possible or feasible or even necessary in certain special or typical sitations.
Personally I would create a Role class like Yassir
But If you want to use the structure that you have at the moment then create a view that contains the foriegn Key to your Person Table and the Role Description.
Modify the Set mapping table to point at your new view
Then modify your Role mapping so that it is a property instead of the many to one mapping.
However taking this approach I think will mean that you will not be able to update your role as it is reerencing a view.
Edit: To update the role you could add <sql-insert>,<sql-update> and <sql-delete> to your mapping file so that the cascade-all will work
i don't think it is possible to map many-to-one to a primitive type if i were you i would add a Role class to the model
This the biggest turn off of the whole OO purist thing.
Surely the goal is to have a working application. Not somebodies version of a perfect class hierarchy. So what if you have to code "prObject.Role.Name " instead of "prObject.Role". How does this help you make a better more reliable program?
From the application design purist point of view what you want is just plain wrong. A person can have several roles, a role can usually be assigned to several people.
Why go to all this trouble to enforce an unrealistic one role per person class hierachy when the undelaying data model is many roles per person?
If you really do have an "only one role per person" rule then it should be refleced in the underlying data model.