views:

244

answers:

2

Hello,

with fluent nhibernate, is there a way to dynamically switch the table of a mapping at runtime?

For example:

public class XYClassMap : ClassMap<XY>
{
  public XYClassMap( )
  {
    Table("XYTable");
    Id(d => d.Id).GeneratedBy.Identity();
    Map(d => d.Value);
    (...)

Given that there are multiple plugins, each of them uses this one class, but they need to work with different tables. I am looking for something like this:

public class XY {
  public string Tablename {get; set;}
}

public class XYClassMap : ClassMap<XY>
{
  public XYClassMap( )
  {
    Table(Tablename);
    Id(d => d.Id).GeneratedBy.Identity();
    Map(d => d.Value);
    (...)

So every action method could work with the same class and only would need to set this one property "Tablename".

Thanks for any help,

Steffen

+1  A: 

Mappings are compiled on application startup, and once that's happened they cannot be changed.

If your plugins use different tables, then by definition they aren't the same entities (and thus the same mappings). If your plugins all define different tables which all have the same structure, then you need separate mappings but you might be able to abstract the actual definitions.

Something like this, perhaps: each plugin defines it's own mapping for this table, which derive from an abstract class containing the actual mappings except for the table name.

public abstract class PluginMap<T> : ClassMap<T> where T : IPlugin
{
  public PluginMap()
  {
    Id(d => d.Id).GeneratedBy.Identity();
    Map(d => d.Value);
  }
}

public class PluginOneMap : PluginMap<PluginOne>
{
  public PluginOneMap()
  {
    Table("PluginOne");
  }
}

public class PluginTwoMap : PluginMap<PluginTwo>
{
  public PluginTwoMap()
  {
    Table("PluginTwo");
  }
}

Alternatively, you could define them as subclasses in an table-per-subclass or table-per-inheritance-hierarchy.

James Gregory
This is something I tried (failed at first and gave up due to schedule pressure). Thanks very much, i will check it out as soon as I´m at my development PC and will come back here ;) Great work btw, keep it up!
Steffen
Fantastic! It works perfectly. I used your idea of mapping the generic base class, import all models from plugins via MEF and made the plugin repository fetch the data like this:public List<T> GetData<T>(int id, string modelClassname) where T : IData { return session.Linq<T>(modelClassname).Where(d => d.ObjectId == id).ToList(); }Thanks for your inspiration, I´ll accept immediately :)
Steffen
Glad to hear you got it working :)
James Gregory
A: 

Hi,

I encountered a similar situation in my project. I have several tables which have only two columns, CODE, and DESCR and these will be referenced by a single main table through a column.

I used the above method which James Gregory has mentioned. See the following sample code:

I have defined a Class called "Codef":

public class Codef : IEquatable<Codef>
    {

        public virtual int Code { get; set; }
        public virtual string Descr { get; set; }
    }



public abstract class CodefMap<T> : ClassMap<T> where T : Codef
{
    public CodefMap()
    {
        Id(x => x.Code, "CODE");
        Map(x => x.Descr, "DESCR");
    }
}

I used the above codefMap for two different entities CDAssignBy and CDChecked

public class CDAssignBy : Codef
    {
    }

public class CDChecked : Codef
    {
    }

And their Maps as:

public class CDCheckedMap : CodefMap<CDChecked>
    {
        public CDCheckedMap()
        {
            Table("CD_CHECKED");
        }
    }

public class CDAssignByMap : CodefMap<CDAssignBy>
    {
        public CDAssignByMap()
        {
            Table("CD_ASSIGNBY");
        }
    }

The mappings work good. BUT, the problem is, when I try to save these objects in the Data Table, the Code (which is the ID) is assigned an incremental value:

var checked1 = new CDChecked { Code = 8, Descr = "Unknown" };
var assignby1 = new CDAssignBy { Code = 1, Descr = "ID Assignment form" };

var recipient1 = new RecipientTest { Crid = 5018, Checked = checked1, AssignBy = assignby1};

The Database table however has Code "1" for the checked in and "2" for assignby.

How can I make the ID (code) independent.

Thank you very much for your help.

Aparna
If i understand you correctly, you could map your Id Column like this: Id(x => x.Code, "CODE").GeneratedBy.Assigned();
Steffen