Basically, I need to set a property to the results of a query that uses data from the parent object.
With the domain model below, I need to set the C property of EntityB using data from both EntityA and EntityB.
Also, I need to set the A property of EntityB to be the actual instance of EntityA that is its parent.
Query:
Set EntityB.C = (select * from EntityC where SomeProperty = EntityB.SomeProperty and AnotherProperty = EntityB.A.AnotherProperty);
SomeProperty and AnotherProperty are not just keys.
class EntityA
{
public IList<EntityB> B
{
get;
set;
}
}
class EntityB
{
public EntityA A
{
get;
set;
}
public EntityC C
{
get;
set;
}
}
class EntityC
{
...
}
I need a way to execute code (to run the query and assign to property) for each entity returned. I came close using the onload method of an interceptor, but I am looking for another way. Perhaps using a Result Transformer or a Projection?
First of all, if you're using NHibernate properly, the properties and associations should be automatically done for you by the framework. If they're not, then you don't have it set up correctly...
As for doing a query in a property... this is usually not recommended (abstract it into a utility class, or at the very least a function call), but I do remember seeing some way on here how to do it.
There are actually two questions.
Question 1: How to have a property that is loaded by some query?
Ask your self if it really needs to be in the entity. Consider to have a DTO (data transfer object) that holds data from different entities and queries instead.
If you're sure that you need this property in the entity, take a look at formulas for single ended properties and filters for collections.
I can't provide more detailed information, because your question is highly general, and it depends on the actual problem. But you should find a solution by starting with the given links.
Question 2: How can I have a property pointing to the parent?
Very easy: By just implementing the property and map the collection of children (B) "inverse=true". Implement your entities the way that they consistently point to the correct parent.
Why is NH not doing this for you? Because NH's responsibility is only to persist your entities to the database. NH does not make any changes on the data by its own. This is responsibility of your business logic.
Note: your application should also be able to run without NH, eg in a unit test. So relations should be managed in your code.
Related
I would like to de-couple my business data entities from my database data entities, and in this way make my application a bit more "data source independent", and in this way to switch data source all I would need to do is to create a few new repositories for the new data source.
However, I cant quite make up my mind of how to do the mapping.
My current data source is a "database" from Parse.com, and in my first attempt to do the mapping I were using AutoMapper.
What if one if my entities has a reference to itself? or what if one of the "child entities" has a reference back to its parent (sort of as EF does it)?
Class ParentClass
{
public string Name { get;set }
public IEnumerable<ChildClass> Children { get;set; }
}
Class ChildClass
{
public string Name { get;set }
public ParentClass Parent{ get;set; }
}
I assume that if I map this up, it would end up in a loop?
Another problem I'm having is that what if for instance Children would have some really deep reference properties?
Lets for instance pretend that a ChildClass looks like this
Class ChildClass
{
public string Name { get;set }
public ParentClass Parent { get;set; }
public IEnumerable<ChildClass> Children { get;set; }
}
I know this might be a stupid example, but in this case a ChildClass object could have a very deep going reference to a bunch of children and these children might have a bunch of children and so forth.
If I would map this using AutoMapper I would end up actually mapping all these children until there is no children left to map. But what if I'm not actually in need of all the "sub-children"?
Is there a way to make it "lazy load" the children on property use?
As an example:
myParentObject.Children.FirstOrDefault().Children.FirstOrDefault().Children.FirstOrDefault()
That would cause the Children property to only get loaded "on call"
Any suggestions as to how to map your data entities to business entities?
I assume that what I'm actually looking for is something that makes it possible to have custom business entities that's treated in the same way as entity framework treats its entities.
Your repositories could return simple poco dto objects (yes, I know the "o" in poco and dto already stands for "object"). Theese do not need to have such complexities like a backlink to the parent. They are just hierarchical. Master with list of details and so on. Some have references to some lookups. Here you could get into trouble if two objects point to the same lookup object and you can't manage to make them the same. Identity Map Pattern http://en.wikipedia.org/wiki/Identity_map_pattern or Value Object Pattern http://en.wikipedia.org/wiki/Value_object comes to help here.
Now your Mapper could be in an own assemlby that references your business entities and the dtos. So your business entities and dtos need not to know each other. In this way you have a maximum of decoupling and independance.
Your Repository should be different for every use case and should "know" which data is needed to which depth and load it accordingly. No almighty "ContactReposiory" that always loads the adresses even when not needed in all use cases. And don't use lazy loading in production. You could end up with a lot of (performance) trouble with it. (Traversing with two litte foreach could end up in 1000th of database roundtrips).
Your mapper could use automapper if suitable at least for the easy parts. The complex parts you could implement the hard way, by hand.
In the entity designer I set the conditional mapping on an entity where it filters all customers by an 'isactive' field.
That works great no problem with that, but the problem comes in my linq.
What happens when I need to set a customer to 'IsActive=false'. The property isn't mapped to my entity because the condition is mapped, but in Linq I can't find a way to change that.
using (var db = new CustDbConn())
{
Customer customer= db.Customers.Single(p => p.Id == idFromEmail);
customer.IsActive = false; //<----NOT FOUND, can not resolve 'isActive'
}
There has to be a way to access and change the conditions in LINQ, can someone shed some light on this? I thought about bypassing the model and just updating it using SqlCommand, but I shouldn't have to go through all that.
You can't change model (that's you're trying to do) using LINQ query.
The only way to manipulate IsActive property is to bring it into Customer model, and throw away conditional mapping.
UPD.
You're misunderstanding the main purpose of conditional mapping - inheritance.
Note, that using EF you don't work with database tables, you work with entity types. All you have, is a model. If any table field is missing from model, than yes, you can't access it via model. With reference to your question, yes, you can't change patients activity status, because there's no activity status in the model.
And yes, if you plan to use some sort of deletion/activity marker (like IsActive in you sample), you have to include it in your queries, otherwise you'll get inactive/deleted items in results. Of course, you can make helper/repository/wrapper/etc to automate it:
interface IEntity
{
int Id { get; }
bool IsActive { get; set; }
}
interface IRepository<T>
where T : IEntity
{
IQueryable<T> Get(bool includeInactiveEntities = false);
}
I'd like to know if the next problem can be solved in a different way in NHibernate.
Let's say we've this domain:
public class A
{
public virtual B LastAssociationWithB { get; set; }
public virtual ICollection<B> CollectionAssociationOfB { get; set; }
}
public class B
{
public virtual DateTime DateAdded { get; set; }
}
The LastAssociationWithB property represents one of the B persistent objects associated in the CollectionAssociationOfB collection property.
Actually, LastAssociationWithB represents the last B persistent object added by date.
So, in the domain, when a new B is added to CollectionAssociationOfB, it's also assigned to LastAssociationWithB.
This is a good way of later turning code into less complex LINQ queries.
Anyway, my question is: do you know any other approach to this? For example, some kind of many-to-one association that produces a SQL join under the hoods so you wouldn't need to have an explicit 1:n relation in the A table but it would maintain the class property?
Or is my current approach the recommended way of solving this scenario?
Side note: in the real-world scenario that CollectionAssociationOfB is an ordered list as ordering is specified in the NHibernate mapping configuration.
You could specify the relationship using a formula:
whether this is better or not is debatable.. it depends on your circumstances - one the one hand it ensures consistency, but on the other hand it will probably have a performance penalty when querying - so it really depends on your own specific case.
Another alternative is to use a trigger on insert into B to update the column in A. This has the downside of moving logic into the database, but it would ensure consistency without the potential performance penalty.
You could also achieve the equivalent of a trigger by using an NHibernate event to intercept saving B and then updating A - with the benefit of the logic remaining in your code, but the downside that any direct updates to the database could introduce inconsistency.
Of course both trigger options obfuscate the logic somewhat, as opposed to having a method on A or B that does the logic. I would personally probably put a method in A to add a new B and update the association, but then you would need to ensure that no-one updates the B collection directly and bypasses your method.
I try to find out how to identify that parent object is Dirty when one of the objects in the child collection was changed by using the features of the NHibernate context.
I mean for the following case:
public class Parent
{
public IList<Child> Childs { get; set; }
}
public class Child
{
public String Name {get; set; }
}
...
var parent = session.Get<Parent>(1);
parent.Childs[0].Name = "new name";
// here <code>session.IsEntityDirty(parent)</code> should return true
I know about extensions to the ISession like here http://nhibernate.info/doc/howto/various/finding-dirty-properties-in-nhibernate.html and here for collection NHibernate: Find dirty collections. But neither first (it tracks just properties), nor second (it tracks just operations add/delete on collection object) work.
I want also to mention that I prefer to use plain POCOs instead of STEs.
I would be very appreciate for a solution.
It does not look if NHibernate is checking if the the object graph is dirty but on the entity itself. So it ignores collections and other references.
If you follow the code
EntityEntry oldEntry = persistenceContext.GetEntry(entity);
Object[] oldState = oldEntry.LoadedState;
The oldState only includes the original values of the entity, but includes the current values of the collection. So my guess is that NHibernate does not take that into account but does another loop somewhere to loop through those entities in the list and check them separately.
The way I would do it is by looping through the properties of the entity and check that with session.IsDirtyProperty skipping over collections and other entity type properties, but then looping through collections and for each entity in the collection checking against that entity's properties.
Remember that your session will need to stay open and not flushed for this to work before checking, if the entity gets detached from the session there won't be a way to use NHibernate to check if it is dirty.
It is also not recommended to keep a session open for a long time, you should use it and dispose it when you done.
I'm reading through Pro ASP.NET MVC 3 Framework that just came out, and am a bit confused about how to handle the retrieval of aggregate objects from a data store. The book uses Entity framework, but I an considering using a mini-ORM (Dapper or PetaPoco). As an example, the book uses the following objects:
public class Member {
public string name { get; set; }
}
public class Item {
public int id { get; set; }
public List<Bid> bids { get; set; }
}
public class Bid {
public int id { get; set; }
public Member member { get; set; }
public decimal amount { get; set; }
}
As far as I'm into the book, they just mention the concept of aggregates and move on. So I am assuming you would then implement some basic repository methods, such as:
List<Item> GetAllItems()
List<Bid> GetBidsById(int id)
GetMemberById(int id)
Then, if you wanted to show a list of all items, their bids, and the bidding member, you'd have something like
List<Item> items = Repository.GetAllItems();
foreach (Item i in items) {
i.Bids = Repository.GetBidsById(i.id);
}
foreach (Bid b in items.Bids) {
b.Member = Repository.GetMemberById(b.id);
}
If this is correct, isn't this awfully inefficient, since you could potentially issue thousands of queries in a few seconds? In my non-ORM thinking mind, I would have written a query like
SELECT
item.id,
bid.id,
bid.amount,
member.name
FROM
item
INNER JOIN bid
ON item.id = bid.itemId
INNER JOIN member
ON bid.memberId = member.id
and stuck it in a DataTable. I know it's not pretty, but one large query versus a few dozen little ones seems a better alternative.
If this is not correct, then can someone please enlighten me as to the proper way of handling aggregate retrieval?
If you use Entity Framework for you Data Access Layer, read the Item entity and use the .Include() fluent method to bring the Bids and Members along for the ride.
An aggregate is a collection of related data. The aggregate root is the logical entry point of that data. In your example, the aggregate root is an Item with Bid data. You could also look at the Member as an aggregate root with Bid data.
You may use your data access layer to retrieve the object graph of each aggregate and transforming the data for your use in the view. You may even ensure you eager fetch all of the data from the children. It is possible to transform the data using a tool like AutoMapper.
However, I believe that it is better to use your data access layer to project the domain objects into the data structure you need for the view, whether it be ORM or DataSet. Again, to use your example, would you actually retrieve the entire object graph suggested? Do I need all items including their bids and members? Or do I need a list of items, number of bids, plus member name and amount for the current winning bid? When I need more data about a particular item, I can go retrieve that when the request is made.
In short, your intuition was spot-on that it is inefficient to retrieve all that data, when a projection would suffice. I would just urge you to limit the projection even further and retrieve only the data you require for the current view.
This would be handled in different ways depending on your data access strategy. If you were using NHibernate or Entity Framework, you can have the ORM automatically populate these properties for you eagerly, lazy load them, etc. Entity Framework calls them "Navigation Properties", I'm not sure that NHibernate has a specific name for these "child properties" or "child collections".
In old-school ADO.NET, you might do something like create a stored procedure that returns multiple result sets (one for the main object and other result sets for your child collections or related objects), which would let you avoid calling the database multiple times. You could then iterate over the results sets and hydrate your object with all its relationships with one database call, and inside of a single repository method.
Where ever in your system you do the data retrieval, you would program your orm of choice to do an eager fetch of the related objects (aggregates).
Using what kind of data access method depends on your project.
Convenience vs performance.
Using EF or Linq to SQL really boosts the coding speed. When talking about performance, you really should care about every sql statement you deliver to the database.
No ORM can do both.
You can treat the read (query) and the write (command) side of the model separately.
When you want to mutate the state of your Aggregate, you load the Aggregate Root (AR) via a repository, mutate its state using the intention revealing public methods on the AR, then save the AR with the repository back again.
On the read side however, you can be as flexible as you want. I don't know Entity Framework, but with NHibernate you could use the QueryOver API to generate flexible queries to populate DTO's designed to be consumed by the client, whether it be a service or a View. If you want more performance you could go with Dapper. You could even use Stored Procs that projects itself to a DTO, that way you can be as efficient in the DB layer as possible.