NHibernate动态添加表

NHibernate动态添加表

设置和动态扩展表差不多,添加了一个模板hbm.xml文件,用于创建动态hbm.xml,HibernateUtil无改动。

 

MappingManger添加了两个方法

 1      public static void UpdateClassMapping(DynamicTestModel dynamicModel)

 2         {

 3             var session = HibernateUtil.Instance.CurrentSession;

 4             var fileName = "hbm_template/Template.hbm.xml";

 5             var file = File.ReadAllText(fileName);

 6             file = file.Replace("@assembly", dynamicModel.GetType().Assembly.GetName().Name)

 7                 .Replace("@namespace", dynamicModel.GetType().Namespace)

 8                 .Replace("@class", dynamicModel.EntityName)

 9                 .Replace("@table", "Dynamic_" + dynamicModel.EntityName);

10 

11             var xDocument = new XmlDocument();

12             xDocument.LoadXml(file);

13 

14             var dynamicElements = xDocument.DocumentElement.GetElementsByTagName("dynamic-component");

15             XmlElement dynamicElement = null;

16             if (dynamicElements.Count > 0)

17             {

18                 dynamicElements[0].InnerXml = string.Empty;

19                 dynamicElement = dynamicElements[0] as XmlElement;

20             }

21 

22             foreach (DictionaryEntry property in dynamicModel.CustomProperties)

23             {

24                 var newElement = CreatePropertyElement(xDocument, dynamicElement.NamespaceURI, property);

25                 dynamicElement.AppendChild(newElement);

26             }

27 

28             Console.WriteLine(xDocument.OuterXml);

29             xDocument.Save("hbm/" + dynamicModel.EntityName + ".hbm.xml");

30         }

31 

32         private static XmlElement CreatePropertyElement(XmlDocument document, string parentNamespace, DictionaryEntry property)

33         {

34             var element = document.CreateElement("property", parentNamespace);

35 

36             element.SetAttribute("name", property.Key as string);

37             element.SetAttribute("column", property.Key as string);

38             element.SetAttribute("type", property.Value.GetType().Name);

39             element.SetAttribute("not-null", "false");

40             return element;

41         }

 

CustomizableEntity类添加了一个属性

public string auto_id { get; set; }

 

创建类DynamicTestModel

 1 namespace DynamicTableTest.DynamicTable

 2 {

 3     public class DynamicTestModel : CustomizableEntity

 4     {

 5         public string EntityName { get; set; }

 6 

 7 

 8         public DynamicTestModel(string entityName)

 9         {

10             // TODO: Complete member initialization

11             this.EntityName = entityName;

12         }

13     }

14 }

 

添加DynamicEntityTuplizer

  1 using NHibernate;

  2 using NHibernate.Mapping;

  3 using NHibernate.Properties;

  4 using NHibernate.Proxy;

  5 using NHibernate.Proxy.Map;

  6 using NHibernate.Tuple;

  7 using NHibernate.Tuple.Entity;

  8 using System.Collections.Generic;

  9 

 10 namespace DynamicTableTest.DynamicTable

 11 {

 12     public class DynamicEntityTuplizer : AbstractEntityTuplizer

 13     {

 14         private static readonly IInternalLogger log = LoggerProvider.LoggerFor(typeof(PocoEntityTuplizer));

 15 

 16         private static readonly DynamicModelAccesser Accessor = new DynamicModelAccesser();

 17         private sealed class DynamicModelMapInstantiator : IInstantiator

 18         {

 19             private readonly string entityName;

 20             private readonly HashSet<string> isInstanceEntityNames = new HashSet<string>();

 21 

 22             private PersistentClass mappingInfo;

 23 

 24             public DynamicModelMapInstantiator()

 25             {

 26                 entityName = null;

 27             }

 28 

 29             public DynamicModelMapInstantiator(PersistentClass mappingInfo)

 30             {

 31                 this.mappingInfo = mappingInfo;

 32                 entityName = mappingInfo.EntityName;

 33                 isInstanceEntityNames.Add(entityName);

 34                 if (mappingInfo.HasSubclasses)

 35                 {

 36                     foreach (PersistentClass subclassInfo in mappingInfo.SubclassClosureIterator)

 37                         isInstanceEntityNames.Add(subclassInfo.EntityName);

 38                 }

 39             }

 40             

 41             public object Instantiate(object id)

 42             {

 43                 return Instantiate();

 44             }

 45 

 46             public object Instantiate()

 47             {

 48                 var model = new DynamicTestModel(entityName);

 49                 return model;

 50             }

 51 

 52             public bool IsInstance(object obj)

 53             {

 54                 var that = obj as DynamicTestModel;

 55                 if (that != null)

 56                 {

 57                     if (entityName == null)

 58                     {

 59                         return true;

 60                     }

 61                     string type = that.EntityName;

 62                     return type == null || isInstanceEntityNames.Contains(type);

 63                 }

 64                 else

 65                 {

 66                     return false;

 67                 }

 68             }

 69         }

 70 

 71         public DynamicEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappingInfo)

 72             : base(entityMetamodel, mappingInfo)

 73         {

 74             // NH different behavior fo NH-1587

 75             Instantiator = BuildInstantiator(mappingInfo);

 76         }

 77 

 78         public override System.Type ConcreteProxyClass

 79         {

 80             get { return typeof(DynamicTestModel); }

 81         }

 82 

 83         public override bool IsInstrumented

 84         {

 85             get { return false; }

 86         }

 87 

 88         public override System.Type MappedClass

 89         {

 90             get { return typeof(DynamicTestModel); }

 91         }

 92 

 93         public override EntityMode EntityMode

 94         {

 95             get { return EntityMode.Map; }

 96         }

 97 

 98         protected override IGetter BuildPropertyGetter(NHibernate.Mapping.Property mappedProperty, PersistentClass mappedEntity)

 99         {

100             return BuildPropertyAccessor(mappedProperty).GetGetter(null, mappedProperty.Name);

101         }

102 

103 

104 

105         private IPropertyAccessor BuildPropertyAccessor(NHibernate.Mapping.Property property)

106         {

107             return Accessor;

108         }

109 

110         protected override ISetter BuildPropertySetter(NHibernate.Mapping.Property mappedProperty, PersistentClass mappedEntity)

111         {

112             return BuildPropertyAccessor(mappedProperty).GetSetter(null, mappedProperty.Name);

113         }

114 

115         protected override IInstantiator BuildInstantiator(PersistentClass mappingInfo)

116         {

117             return new DynamicModelMapInstantiator(mappingInfo); // new DynamicMapInstantiator(mappingInfo);

118         }

119 

120         protected override IProxyFactory BuildProxyFactory(PersistentClass mappingInfo, IGetter idGetter,

121                                                                     ISetter idSetter)

122         {

123             IProxyFactory pf = new MapProxyFactory();

124             try

125             {

126                 //TODO: design new lifecycle for ProxyFactory

127                 pf.PostInstantiate(EntityName, null, null, null, null, null);

128             }

129             catch (HibernateException he)

130             {

131                 log.Warn("could not create proxy factory for:" + EntityName, he);

132                 pf = null;

133             }

134             return pf;

135         }

136     }

137 }

 

DynamicInterceptor

 1 using NHibernate;

 2 using NHibernate.Mapping;

 3 using System.Collections.Generic;

 4 

 5 namespace DynamicTableTest.DynamicTable

 6 {

 7     public class DynamicInterceptor : EmptyInterceptor

 8     {

 9         private readonly string entityName;

10         private readonly HashSet<string> isInstanceEntityNames = new HashSet<string>();

11 

12         public DynamicInterceptor()

13         {

14             entityName = null;

15         }

16 

17         public DynamicInterceptor(PersistentClass mappingInfo)

18         {

19             entityName = mappingInfo.EntityName;

20             isInstanceEntityNames.Add(entityName);

21             if (mappingInfo.HasSubclasses)

22             {

23                 foreach (PersistentClass subclassInfo in mappingInfo.SubclassClosureIterator)

24                     isInstanceEntityNames.Add(subclassInfo.EntityName);

25             }

26         }

27 

28         public override string GetEntityName(object entity)

29         {

30             var dynamicEntity = entity as DynamicTestModel;

31             if (dynamicEntity == null) {

32                 return base.GetEntityName(entity);

33             }

34             else

35             {

36                 return dynamicEntity.EntityName;

37             }

38         }

39     }

40 }

 

DynamicModelAccesser
  1 using NHibernate.Engine;

  2 using NHibernate.Properties;

  3 using System;

  4 using System.Collections;

  5 using System.Reflection;

  6 

  7 namespace DynamicTableTest.DynamicTable

  8 {

  9     public class DynamicModelAccesser : IPropertyAccessor

 10     {

 11         private static readonly string CUSTOM_PROPERTY_NAME = "CustomProperties";

 12         private static readonly string AUTO_ID_NAME = "auto_id";

 13 

 14         public IGetter GetGetter(System.Type theClass, string propertyName)

 15         {

 16             return new DynamicGetter(propertyName);

 17         }

 18 

 19         public ISetter GetSetter(System.Type theClass, string propertyName)

 20         {

 21             return new DynamicSetter(propertyName);

 22         }

 23 

 24         public bool CanAccessThroughReflectionOptimizer

 25         {

 26             get { return false; }

 27         }

 28 

 29         [Serializable]

 30         public sealed class DynamicSetter : ISetter

 31         {

 32             private readonly string name;

 33 

 34             internal DynamicSetter(string name)

 35             {

 36                 this.name = name;

 37             }

 38 

 39             public MethodInfo Method

 40             {

 41                 get { return null; }

 42             }

 43 

 44             public string PropertyName

 45             {

 46                 get { return null; }

 47             }

 48 

 49             public void Set(object target, object value)

 50             {

 51                 if (CUSTOM_PROPERTY_NAME.Equals(name))

 52                 {

 53                     (target as DynamicTestModel).CustomProperties = (IDictionary)value;

 54                 }

 55                 else if (AUTO_ID_NAME.Equals(name))

 56                 {

 57                     (target as DynamicTestModel).auto_id = value as string;

 58                 }
59          else
60          {
61   (target as DynamicTestModel).CustomProperties[name] = value;
62 }
63 } 64 } 65 66 [Serializable] 67 public sealed class DynamicGetter : IGetter 68 { 69 private readonly string name; 70 71 internal DynamicGetter(string name) 72 { 73 this.name = name; 74 } 75 76 public MethodInfo Method 77 { 78 get { return null; } 79 } 80 81 public object GetForInsert(object owner, IDictionary mergeMap, ISessionImplementor session) 82 { 83 return Get(owner); 84 } 85 86 public string PropertyName 87 { 88 get { return null; } 89 } 90 91 public System.Type ReturnType 92 { 93 get { return typeof(object); } 94 } 95 96 public object Get(object target) 97 { 98 if (CUSTOM_PROPERTY_NAME.Equals(name)) 99 { 100 return (target as DynamicTestModel).CustomProperties; 101 } 102 else if (AUTO_ID_NAME.Equals(name)) 103 { 104 return (target as DynamicTestModel).auto_id; 105 } 106 return (target as DynamicTestModel).CustomProperties[name]; 107 } 108 } 109 } 110 }

 

模板hbm.xml

 1 <?xml version="1.0" encoding="utf-8" ?>

 2 <hibernate-mapping 

 3   xmlns="urn:nhibernate-mapping-2.2"

 4   assembly="@assembly"

 5   namespace="@namespace"

 6   auto-import="true" 

 7   default-access="property" 

 8   default-cascade="none" 

 9   default-lazy="true">

10 

11   <class entity-name="@class" table="@table">

12     <tuplizer class="DynamicEntityTuplizer" entity-mode="dynamic-map" />

13     <id name="auto_id" column="auto_id" type="string">

14       <generator class="uuid.hex" />

15     </id>

16     <dynamic-component insert="true" name="CustomProperties" optimistic-lock="true" unique="false" update="true">

17     </dynamic-component>

18   </class>

19 </hibernate-mapping>

 

最后是测试代码,QueryOver中where在这里会有问题,改用hql语句实现了

 1 using DynamicTableTest.DynamicTable;

 2 using System;

 3 using System.Linq;

 4 

 5 namespace DynamicTableTest

 6 {

 7     class Program

 8     {

 9         static void Main(string[] args)

10         {

11             DynamicModelMethod();

12 

13             Console.Read();

14         }

15 

16         private static void DynamicModelMethod()

17         {

18             var entityName = "Test_Role";

19             var columnName = "Name";

20             var columnRole = "Role";

21             var columnCreateTime = "Create_Time";

22 

23             var dynamicEntity = new DynamicTestModel(entityName);

24             var name = Guid.NewGuid().ToString();

25             dynamicEntity.SetValueOfCustomField(columnName, name);

26             dynamicEntity.SetValueOfCustomField(columnRole, 31);

27             dynamicEntity.SetValueOfCustomField(columnCreateTime, DateTime.Now);

28 

29             MappingManager.UpdateClassMapping(dynamicEntity);

30             HibernateUtil.Instance.Reset();

31 

32             var session = HibernateUtil.Instance.CurrentSession;

33 

34             var trans = session.BeginTransaction();

35             try

36             {

37                 //add

38                 var id = session.Save(entityName, dynamicEntity);

39                 Console.WriteLine("first name: " + name);

40 

41                 //get

42                 var role = (DynamicTestModel)session.Get(entityName, id);

43                 var storedName = role.GetValueOfCustomField(columnName);

44                 Console.WriteLine("second name: "+storedName);

45 

46                 //update

47                 var newName = Guid.NewGuid().ToString();

48                 role.SetValueOfCustomField(columnName, newName);

49                 session.SaveOrUpdate(entityName, role);

50 

51                 //get 

52                 role = (DynamicTestModel)session.Get(entityName, id);

53                 storedName = role.GetValueOfCustomField(columnName);

54                 Console.WriteLine("third name: " + storedName);

55 

56                 //delete

57                 session.Delete(entityName, role);

58                 role = (DynamicTestModel)session.Get(entityName, id);

59                 Console.WriteLine(role == null);

60                 

61                 var roles = session.QueryOver<DynamicTestModel>(entityName).List();

62                 foreach (var roleItem in roles)

63                 {

64                     Console.WriteLine(roleItem.ToString());

65                 }

66                 Console.WriteLine("###########################################");

67                 roles = session.CreateQuery(string.Format("from {0} where {1}='{2}'", entityName, columnName, "abc")).Enumerable<DynamicTestModel>().ToList();

68 

69                 foreach (var roleItem in roles)

70                 {

71                     Console.WriteLine(roleItem.ToString());

72                 }

73 

74                 trans.Commit();

75             }

76             catch (Exception ex)

77             {

78                 trans.Rollback();

79                 Console.WriteLine(ex.ToString());

80             }

81         }

82     }

83 }

Over!

你可能感兴趣的:(Hibernate)