3

User always has one Wallet. One Wallet belongs always to one User.

Since I want to separate money wallet related properties I was create Wallet object and to be able to track money transactions, ... I created

public Wallet : Entity<int>
{
    public double Amont {get; set;}
    public IList<MoneyTrans> Transactions {get; set;}
}

Since this is obviously one to one relationship is it ok to map using one to one relationship?

Is one to one bad strategy?

user1765862
  • 13,635
  • 28
  • 115
  • 220
  • If that is the logical design, why would it be a bad strategy? Do you mean if you needed to change it in future? – Adam Houldsworth May 02 '14 at 10:14
  • nope, but I read tons of pages where one to one are critises. Thanks – user1765862 May 02 '14 at 10:18
  • can you please provide links to a few so that we can read it and let you know what it exactly meant? – samar May 02 '14 at 10:21
  • Also check this link out. A possible duplicate. http://stackoverflow.com/questions/3939589/database-design-should-one-to-one-relationships-be-avoided – samar May 02 '14 at 10:22
  • http://stackoverflow.com/questions/9562507/one-to-one-mapping-in-nhibernate-3-2-mapping-by-code – user1765862 May 02 '14 at 10:23
  • @user1765862 So if you have read tons of pages saying they are bad, what is the purpose of the question here? If you want my opinion, no they are not inherently bad, but I don't know enough specifically about nHibernate to know if they are "bad" in that context. – Adam Houldsworth May 02 '14 at 10:23
  • @user1765862 The answer you provided in this link contains an answer and reasoning: http://stackoverflow.com/questions/9562507/one-to-one-mapping-in-nhibernate-3-2-mapping-by-code – Adam Houldsworth May 02 '14 at 10:25
  • Purpose is that I want to here more cause I'm not convinced that are bad in my concrete case. – user1765862 May 02 '14 at 10:40

2 Answers2

4

I had to append answer, with opposite point of view. Do not use one-to-one mapping. At least with NHibernate.

I am not talking about the conceptual domain driven design. Just about my experience with DB design and NHibernate usage.

1) one-to-one - Rigid DB design

First of all the desing with shared primary keys (except of inheritance) could lead to many issues later, when the Business requirements are changed.

The typical scenario, very similar to example 23.2. Author/Work, where Author is mapped one-to-one to Person. Therefore, the id (primary key) of the Author comes from a Person (id). Sooner or later, Business will come and ask could we have to person mapped to Author (see Lars Kepler example)

What I am trying to say here is: Chapter 24. Best Practices (let me cite one point)

Declare identifier properties on persistent classes.

NHibernate makes identifier properties optional. There are all sorts of reasons why you should use them. We recommend that identifiers be 'synthetic' (generated, with no business meaning) and of a non-primitive type. For maximum flexibility, use Int64 or String.

As mentioned here (and from my experience), it is very benefitial to have all entities with their own surrogated primary keys. The changes in relations coming later - will effect just references (on top of surrogated keys), not the table/entities themselves.

2) one-to-one with NHibernate cannot be lazy

In fact this reason is the one, why (despite of the fact I tried few times) currently do not use the one-to-one at all. The one-to-one is not supporting lazy loading. Search for more info but nice explanation could be found here:

As mentioned in one of the links in comments below the question (cite)

  1. You can either include all those attributes as columns into your entity table - but in that case, lots of columns would end up empty for a significant number of the entries.

  2. Or: you can put those "optional" attributes into a separate table, set up a 1:1 (or rather: 0:1) relationship with the base entity table,

Well, with NHiberante you won't get so much improvement. This suggestion is wrong. Lazy loading of one-to-one isn't supported...

SUMMARY:

That's why I would strongly suggest: use many-to-one or one-to-many where possible. You'll gain more...

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • Really good answer, based on my concrete example (User - Wallet) what do you recommend? – user1765862 May 03 '14 at 17:38
  • Wow... sorry, that I missed this answer ;) Well, in this case, I'd like to have direct access from `User` to `Wallet`, so: `User` *(table)* would have the column `WalletId`. Then `User` will have the `many-to-one` reference `public virtual Wallet Wallet { get; set; }` *If needed, the opposite direction could be: 1) Wallet could have a `` of `Users` - but protected, 2) and some virtual/artifical property working with `Users.SingleOrDefault()`*. Because the direction User-Wallet is essential, the `many-to-one` in this case will do the 80% of daily stuff... I'd say – Radim Köhler May 03 '14 at 18:17
  • Thanks again, to conclude does that means that If I want bidirectional relationship UserTable with WalletId and viceversa Wallet table with UserId than I should I use ManyToOne on both sides? – user1765862 May 04 '14 at 09:05
  • Most likely, yes. The best answer is ... try to experiment, play with. At the end, your conclusion could work very well. The most important thing here is to keep tables with their own surrogated keys *(NHibernate will offer us the best then)* Also, the Business layer, and the UI layer, could be publishing a bit different views to our users - in comparison with Data layer *(i.e. it could seem like `one-to-one` to the end user)* – Radim Köhler May 04 '14 at 11:14
3

No it's fine. It's not just about relationships but object orientation. Fundamentaly a Wallet is not an unseverable part of a Person.

Looking beyond that, whilst the wallet might belong to a specific 'John' now, 'James' might be given it as a present. From the data perspective it's much better to just change the WalletId fields of John and James of which one may be null (although not in your case) if they don't have a wallet.

Hoots
  • 1,876
  • 14
  • 23