Well, a very interesting idea - I mean, to keep a parallel data in the database. Worth looking at.
As for hiding, I may agree that this is an anti-pattern... however I hide it behind a repository anyway (because those are pretty weird data structures and actions I need to perform to get them working, and because I need my Item refer to other Products), so why not to make it right and easy to the end... On 7 сен, 22:02, Markus Zywitza <[email protected]> wrote: > A persistent type is simply a class mapped to a table with NH. The idea is > that you don't save just a string with the legacy item id, but a real class > that contains the legacy item id among other (cached) data of the original > item data, depending on stability of the original data. If you decide to > move the items into your main database, you can simply extend this class. > Until then you have to use an anti-corruption-layer to mediate between the > item class in your model and the legacy datastore. > > Trying to hide such an important issue like legacy datastores within > NHibernate is rather an anti-pattern. > > -Markus > > 2009/9/7 queen3 <[email protected]> > > > > > Sorry but I don't understand what do you mean by "persistent type"? Is > > it something like Active Record - a class that has .Load/.Save? I > > don't see how it's different from creating repository inside > > IUserType. > > > And the problem is not transaction-safe creation of a single Item. The > > complete transaction is like: > > 1. Create all product.Items on web service > > 2. Save product into DB now with newly generated Item IDs > > As you can see from the transaction I have to rollback all created > > Items if some of them failed to created or product failed to save to > > database. > > > By the way I found a similar question here and Ayende highly > > recommending not doing so: > >http://markmail.org/message/yixji3gsy4ou4jjj > >http://markmail.org/message/o3vx6bdu5uusmu66 > > > Still this seems to me a very promising solution... > > > On 7 сен, 20:22, Markus Zywitza <[email protected]> wrote: > > > 5. Create a persistent type for Item and reference it. For what to > > include > > > into the type, there is no silver bullet; you have to decide case by > > case, > > > as this also depends on change frequency and required performance. > > > To create and update instances of the Item type from the web service use > > an > > > anti-corruption-layer, embedded into a repository implementation. > > > > -Markus > > > > 2009/9/7 queen3 <[email protected]> > > > > > I have a Product class for which I need IList<Item> Items property. > > > > However, I can only get Item from a legacy external repository (web > > > > service) by string id. So I came with these solutions: > > > > > 1. Use IList<string> ItemIds and do itemRepository.Get(id) when needed > > > > in my client code (controllers). Too manual and not very nice. And it > > > > would be nice to hide the fact that Item is not part of the persisten > > > > store... what if in future we'll finally move Items to the database? > > > > Rewrite all the code? Don't want that. > > > > > 2. Use IUserType and load/save object inside NullSafeSet/Get: > > > > public object NullSafeGet(IDataReader rs, string[] names, object > > > > owner) > > > > { > > > > return new ItemRepository().Get((string) > > > > NHibernateUtil.String.NullSafeGet(rs, names[0])); > > > > } > > > > public void NullSafeSet(IDbCommand cmd, object value, int index) > > > > { > > > > new ItemRepository().Save((Item)value); > > > > cmd.Parameters[index] = ((Item)value).Id; > > > > } > > > > Above (is simplifed but) should probably work very well (though I'm > > > > not expert in IUserType). There's one issue, though... what do I do if > > > > an error occured and I need to rollback changes to Items? There's no > > > > notion of transactions in IUserType. > > > > There's problem with "new ItemRepository()" which is not nice, see (4) > > > > for why. > > > > > 3. So I can do this work in the place where I have access to > > > > transactions: ProductRepository. > > > > public Product BeginTransaction() // actually > > > > DbContext.BeginTransaction() but it doesn't matter > > > > { > > > > itemRepository.BeginTransaction(); > > > > } > > > > public Product Get(int id) > > > > { > > > > var product = Session.Get(id); > > > > foreach (var item in product.Items) > > > > itemRepository.SaveOrUpdate(item); > > > > } > > > > public void Rollback() // actually DbContext.Rollback() but it doesn't > > > > matter > > > > { > > > > itemRepository.Rollback(); > > > > } > > > > Notice that it also makes it easier to couple ProductRepository/ > > > > ItemRepository together since I can inject IItemRepository into > > > > ProductRepository constructor, not just use "new ItemRepository()" > > > > inside IUserType. > > > > But, this way is a bit harder because I > > > > > 4. Somehow combine these ways? From what I see, the (4) does not > > > > conflict with (3), i.e. if ProductRepository correctly align its > > > > transactions with ItemRepository, we're safe? So, IUserType will be > > > > responsible for loading/saving Item instances (no foreach(item) > > > > needed), while ProductRepository will deal with transaction failure > > > > and align calls to itemRepository.BeginTransaction()/Rollback()? Will > > > > it work? I think NO because inside IUserType I use "new ItemRepository > > > > ()"... so unless I have singlton factory IUserType and > > > > ProductRepository will have different ItemRepository instances/ > > > > sessions/transactions... > > > > > So, did anyone experienced the same problem? What is the best solution/ > > > > practices here? --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "nhusers" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/nhusers?hl=en -~----------~----~----~----~------~----~------~--~---
