0

I’ve done some Googling but I have yet to find a solution, or even a definitive answer to my problem.

The problem is simple. I want to dynamically create a table per instance of a dynamically named/created object. Each table would then contain records that are specific to the object. I am aware that this is essentially an anti-pattern but these tables could theoretically become quite large so having all of the data in one table could lead to performance issues.

A more concrete example:

I have a base class/interface ACCOUNT which contains a collection of transactions. For each company that uses my software I create a new concrete version of the class, BOBS_SUB_SHOP_ACCOUNT or SAMS_GARAGE_ACCOUNT, etc. So the identifying value for the class is the class name, not a field within the class.

I am using C# and Fluent nHibernate.

So my questions are:

  1. Does this make sense or do I need to clarify more? (or am I trying to do something I REALLY shouldn’t?)
  2. Does this pattern have a name?
  3. Does nHibernate support this?
  4. Do you know of any documentation on the pattern I could read?

Edit: I thought about this a bit more and I realized that I don't REALLY need dynamic objects. All I need is a way to tie objects with some identifier to a table through NHibernate. For example:

//begin - just a brain dump
public class Account
{
  public virtual string AccountName { get; set; }
  public virtual IList Stuff { get; set; }
}

... somewhere else in code ...

//gets mapped to a table BobsGarageAccount (or something similar)
var BobsGarage = new Account{AccountName="BobsGarage"}; 
//gets mapped to a table StevesSubShop(or something similar)
var StevesSubShop = new Account{AccountName="StevesSubShop"};
//end

That should suffice for what i need, assuming NHibernate would allow it. I am trying to avoid a situation where one giant table would have the heck beat out of it if high volume occurred on the account tables. If all accounts were in one table... it could be ugly.

Thank you in advance.

J R
  • 335
  • 4
  • 8
  • When you create the new concrete object for each company, can you not at that point create a new table and fluent mapping? - sry just re-read, you're creating the concrete objects on the fly. – Hans Jonus Feb 10 '12 at 00:32

2 Answers2

1

Rather than creating a class on the fly, I would recommend a dynamic object. If you implement the right interfaces (one example is here, and in any case you can get there by inheriting from DynamicObject), you can write

dynamic bobsSubShopAccount = new DynamicAccount("BOBS_SUB_SHOP_ACCOUNT");
Console.WriteLine("Balance = {0}", bobsSubShopAccount.Balance);

in your client code. If you use the DLR to implement DynamicAccount, all these calls get intercepted at runtime and passed to your class at runtime. So, you could have the method

public override bool TryGetMember(GetMemberBinder binder, out object result)
{
    if (DatabaseConnection.TryGetField(binder.Name, out result))
        return true;

    // Log the database failure here

    result = null;
    return false; // The attempt to get the member fails at runtime
}

to read the data from the database using the name of the member requested by client code.

I haven't used NHibernate, so I can't comment with any authority on how NHibernate will play with dynamic objects.

Adam Mihalcin
  • 14,242
  • 4
  • 36
  • 52
  • Adam, Thanks for the feedback. I'll look into that while we see if an NHibernate authority weighs in. – J R Feb 09 '12 at 23:24
  • Adam, Thanks again for the feedback. I will look into dynamic objects for future reference. Much appreciated. – J R Feb 10 '12 at 18:07
0

Those classes seem awfully smelly to me, and attempt to solve what amounts to be an actual storage layer issue, not a domain issue. Sharding is the term that you are looking for, essentially.

If you are truly worried about performance of the db, and your loads will be so large, perhaps you might look at partitioning the table instead? Your domain objects could easily handle creating the partition key, and you don't have to do crazy voodoo with NHibernate. This will also more easily permit you to not do nutty domain level things in case you change your persistence mechanisms later. You can create collection filters in your maps, or map readonly objects to a view. The latter option would be a bit smelly in the domain though.

If you absolutely insist on doing some voodoo you might want to look at NHibernate.Shards, it was intended for easy database sharding. I can't say what the current dev state and compatibility is, but it's an option.

Community
  • 1
  • 1
Chad Ruppert
  • 3,650
  • 1
  • 19
  • 19
  • I agree that this is largely a storage issue - my smelly classes are merely a symptom of the problem, I believe. I'll do some research into both sharding and partioning tables. Thanks. – J R Feb 10 '12 at 03:51
  • Please don't be insulted, it is an interesting attempt at a solution, it just would get messy and unnecesarily pollute your code – Chad Ruppert Feb 10 '12 at 03:55
  • Oh, no, not insulted at all! The cleaner the code, the easier to maintain, the happier everyone is. You just introduced a few topics I was unfamiliar with and I need to go do some research. (and maybe learn to spell along the way...) – J R Feb 10 '12 at 04:44
  • Chad, it looks as if partitioning will be the route i attempt to take in the long run. In the short term i am going to just leave everything in one table without partitioning and see how bad it is. don't solve problems you don't have, right? Marked your response as the answer because i think its closer to the direction I should take. – J R Feb 10 '12 at 18:06
  • Thanks, yeah, I was going to mention that you were attempting optimization when there wasn't a need yet. To preplan for table partitioning you might want to decide on a partition key up front (maybe a reference to the client not only in the account class, but also each transaction line item). Then if you do need to partition later, its just doing the sql to use that client's id as the partition key – Chad Ruppert Feb 10 '12 at 18:56
  • Thanks Chad. I'll make a note and come back to this! – J R Feb 14 '12 at 17:14