Any relationship in a non ORM world can be a nightmare, that's why we're using NHibernate. Orphans are handled nicely by NHs Cascade.AllDeleteOrphan.
As for one-to-one vs many-to-one, you're not making the distinction between domain and database. The database doesn't care about shared resources, if one table can have multiple records referencing a single row in another, it's a many-to-one; regardless of whether your domain has that being correct or not. When we're talking about these patterns, we're discussing how the database is mapped - it's irrelevant of your business rules, or preconceptions of what can and can not be shared. A one-to-one is almost never the answer. Unless your tables have identical primary key values, it isn't a one-to-one relationship. These rules are entirely the concern of the domain, and whether you treat it as a one-to-one in that is completely unrelated to the underlying table structure pattern. On Wed, Feb 11, 2009 at 9:28 PM, Chris Marisic <[email protected]> wrote: > > You don't really deal with the fact if you follow the many to 1 > pattern you now have to also deal with orphaned objects. I've > previously developed a system entirely by hand implementing the many > to one pattern. I will never forget the fact that every single insert/ > update of a given type (address, phone) required about 5 procedure/ > function calls to manipulate keeping the ids correct and making sure > records don't become orphaned. > > I'm sure NHibernate offers a way to make it not a catastrophe for the > developer to deal with but I still disagree with it in practice since > I don't believe in most cases where it's used that it's correct. 3 > people sharing an address should be 3 entries in the database in my > opinion. If anyone of them changes or deletes their address it > shouldn't have to figure out if changing their address will impact > others. > > IMO the only time the many to 1 pattern is valid is on something you > own that you share. Say a resource like a golf cart. Many people can > share that golf cart, updating that golf cart should change every > persons view of that golf cart. > > On Feb 11, 4:09 pm, James Gregory <[email protected]> wrote: > > Chris, it definitely shouldn't be a one-to-one. I'd say his mapping is > > correct. If two golfers shared an address, and one of them changed then > > you'd insert a new record for the new address and update the related > golfer, > > it's still a many-to-one. > > Please refer to my blog post about this: > http://blog.jagregory.com/2009/01/27/i-think-you-mean-a-many-to-one-sir/ > > > > If you find yourself suggesting or mapping a one-to-one, then you're > > probably doing it wrong. True one-to-one's are very rare. > > > > On Wed, Feb 11, 2009 at 9:00 PM, Chris Marisic <[email protected]> > wrote: > > > > > I think I'd have to disagree with that being a many to one situation. > > > That in my opinion SHOULD be a one to many. A golfer can have many > > > addresses, if you only care about a single address, it should be a 1 > > > to 1 association. > > > > > Having multiple golfers share 1 address is wrong even if they have the > > > same physical street address. How do you differentiate if the address > > > changes, say becomes a mailbox number. At that point you change the > > > address of one of the golfers you just updated every golfer that had > > > that address. I understand the point of databases is to minimize data > > > duplication but IMO this is a wrong application of it. > > > > > Seeing what you're attempting I'm going to assume most likely in your > > > edit address place you are creating a new address for that person then > > > trying to save the person. This would most likely leave the original > > > address object in the session as transient which gives you this error. > > > My guess would be something along the lines: > > > > > var prevAddress = golfer.Address; > > > > > golfer.Address = new Address(...) > > > > > session.Save(prevAddress) > > > > > session.Save(person) > > > > > session.Flush() > > > > > On Feb 11, 3:43 pm, Ramana Kumar <[email protected]> wrote: > > > > No, I did mean Many to One :-) The Domain Objects are Golfer and > Address > > > > and many Golfers can share the same Address. Per James > > > > "i-think-you-mean-a-many-to-one-sir" G, this should be mapped as Many > to > > > > one. I am just not sure how to do it thru AutoMap conventions. > > > > HTH > > > > Ramana > > > > > > namespace GolfHandicapManager.Core > > > > { > > > > public class Golfer : Entity > > > > { > > > > public Golfer() { } > > > > [DomainSignature] > > > > [NotNullNotEmpty] > > > > public virtual string FirstName { get; set; } > > > > [DomainSignature] > > > > [NotNullNotEmpty] > > > > public virtual string LastName { get; set; } > > > > [NotNullNotEmpty] > > > > public virtual string EmailAddress { get; set; } > > > > public virtual string EmailAddress2 { get; set; } > > > > public virtual string HomePhone { get; set; } > > > > public virtual string CellPhone { get; set; } > > > > public virtual Address Address { get; set; } > > > > } > > > > public class Address : Entity > > > > { > > > > public Address() { } > > > > [DomainSignature] > > > > public virtual string Addr1 { get; set; } > > > > public virtual string Addr2 { get; set; } > > > > [DomainSignature] > > > > public virtual string City { get; set; } > > > > public virtual string State { get; set; } > > > > public virtual string Country { get; set; } > > > > public virtual string ZipCode { get; set; } > > > > } > > > > > > } > > > > On Wed, Feb 11, 2009 at 2:05 PM, Chris Marisic <[email protected]> > > > wrote: > > > > > > > Do you mean One to Many? > > > > > > > convention.OneToManyConvention = m => > > > > > { > > > > > m.Cascade.All(); > > > > > }; > > > > > > > On Feb 11, 1:58 pm, Ramana Kumar <[email protected]> wrote: > > > > > > Hi > > > > > > I am trying to use AutoMap to define behaviour for ManyToOne and > I > > > get > > > > > the > > > > > > following exception > > > > > > > > object references an unsaved transient instance - save the > transient > > > > > > instance before flushing: > > > > > > > > The relevant code is > > > > > > > > public class AutoPersistenceModelGenerator : > > > > > IAutoPersistenceModelGenerator > > > > > > { > > > > > > public AutoPersistenceModel Generate() > > > > > > { > > > > > > AutoPersistenceModel mappings = AutoPersistenceModel > > > > > > .MapEntitiesFromAssemblyOf<Golfer>() > > > > > > .Where(GetAutoMappingFilter) > > > > > > .WithConvention(GetConventions); > > > > > > return mappings; > > > > > > } > > > > > > > > private bool GetAutoMappingFilter(Type t) > > > > > > { > > > > > > return t.Namespace == "GolfHandicapManager.Core"; > > > > > > } > > > > > > private void GetConventions(Conventions c) > > > > > > { > > > > > > c.GetPrimaryKeyNameFromType = type => "ROW_ID"; //DB > has > > > > > ROW_ID > > > > > > as Primary Key > > > > > > c.FindIdentity = type => type.Name == "ID"; // S#arp > > > > > currently > > > > > > uses "ID" > > > > > > // Taken from Ayende Blog > > > > > > c.GetForeignKeyNameOfParent = (type => type.Name + > > > "_ID"); > > > > > > c.GetTableName = type => > > > > > > Inflector.Net.Inflector.Pluralize(type.Name); > > > > > > c.IsBaseType = IsBaseTypeConvention; > > > > > > // Convert PropertyName to Underscore > > > > > > c.AddPropertyConvention(new > > > > > > PascalToUnderscorePropertyConvention()); > > > > > > } > > > > > > > > I am assuming I have to do a "cascade=all" somewhere in there but > do > > > not > > > > > > know how to do it thru a convention. > > > > > > > > Any pointers? > > > > > > Thanks > > > > > > Ramana > > > > > > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Fluent NHibernate" 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/fluent-nhibernate?hl=en -~----------~----~----~----~------~----~------~--~---
