2017-02-09 40 views
0

我的数据库中有一个字段,用于存储整数值并包含在列表中选择的按位值的总和。例如:如何在NHibernate中将按位总和映射到列表中

VALUE DESCRIPTION 
----- ----------- 
    1 Option 1 
    2 Option 2 
    4 Option 3 
    8 Option 4 

比方说,选项2 & 4被选出,所以存储在字段中的值是10

我有一个很难搞清楚(如果它甚至有可能)如何在hbm.xml文件中表示此项。

这里是我想要做一个普通的例子:

产品表列

Id, int 
Name, varchar(25) 
Services, int 

服务表列

Id, int 
Name, varchar(25) 

Product.cs

public class Product 
{ 
    public virtual int Id { get; set; } 
    public virtual string Name { get; set; } 
    public virtual IList<Service> Services { get; set; } 
} 

Service.cs

public class Service 
{ 
    public virtual int Id { get; set; } // bit values: 1, 2, 4, 8, ... 
    public virtual string Name { get; set; } 
} 

Product.hbm.xml

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="AppNS" namespace="AppNS"> 
    <class name="Product" table="Product"> 
     <id name="Id" column="Id" type="int"> 
      <generator class="native"/> 
     </id> 
     <property name="Name" column="Name" type="string"/> 
     <????? name="Services" column="Services" type="AppNS.Service"/> 
    </class> 
</hibernate-mapping> 

Service.hbm.xml

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="AppNS" namespace="AppNS"> 
    <class name="Service" table="Service"> 
     <id name="Id" column="Id" type="int"> 
      <generator class="native"/> 
     </id> 
     <property name="Name" column="Name" type="string"/> 
    </class> 
</hibernate-mapping> 

我需要帮助<? >部分在Product.hbm.xml文件中。

- 编辑 -

最后,我希望能够调用load()方法来获得我的产品型号后面。

Configuration cfg = new Configuration(); 
... 
ISessionFactory sf = cfg.BuildSessionFactory(); 
using (ISession s = sf.OpenSession()) 
{ 
    Product product = s.Load<Product>(100); 
    foreach(Service service in product.Services) 
    { 
     Console.WriteLine(service.Name); 
    } 
} 

输出将是:

Option 2 
Option 4 

回答

1

此类字段应该被映射为一个简单的属性。实体应该将此属性作为标志枚举输入。我不认为你可以直接把它作为一个列表。

您可以改为从映射的枚举中计算您的列表。

[Flags] 
public enum EService 
{ 
    Option1 = 1, 
    Option2 = 2, 
    Option3 = 4, 
    Option4 = 8 
} 

public class Product 
{ 
    public virtual int Id { get; set; } 
    public virtual string Name { get; set; } 
    public virtual EService Services { get; set; } 

    // Coded here for simplicity, though you'd probably do not want such 
    // dependencies here. 
    public virtual List<Service> GetServicesEntities(ISession session) 
    { 
     var services = new List<Service>(); 
     foreach (EService s in Enum.GetValues(typeof(EService))) 
     { 
      if ((Services & s) != 0 && 
       // In case you predefine combinations of options in the enum, you need 
       // this to avoid having them in the list too. 
       IsPowerOfTwo((int)s)) 
      { 
       services.Add(
        // Not a n+1 perf trouble if you have lazy loading batching enabled. 
        session.Load<Service>(s)); 
      } 
     } 
     return services; 
    } 

    // Taken from http://stackoverflow.com/a/600306/1178314 
    private bool IsPowerOfTwo(int x) 
    { 
     return (x != 0) && ((x & (x - 1)) == 0); 
    } 
} 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="AppNS" namespace="AppNS"> 
    <class name="Product" table="Product"> 
     <id name="Id" column="Id"> 
      <generator class="native"/> 
     </id> 
     <property name="Name" /> 
     <property name="Services" /> 
    </class> 
</hibernate-mapping> 

(简体的方式映射,NHibernate的假定列的名字是相同的,如果没有指定属性名称,以及从实体推断属性类型。)

0

尝试XML LINQ

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Xml; 
using System.Xml.Linq; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      string header = 
       "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" + 
       "<hibernate-mapping xmlns=\"urn:nhibernate-mapping-2.2\" assembly=\"AppNS\" namespace=\"AppNS\">" + 
       "</hibernate-mapping>"; 

      Product.products = new List<Product>() { 
       new Product() { Id = 100, Name = "Product", Services = new List<Service>() { 
        new Service() {Id = 1, Name = "Option 1"}, 
        new Service() {Id = 2, Name = "Option 2"}, 
        new Service() {Id = 4, Name = "Option 3"}, 
        new Service() {Id = 8, Name = "Option 4"} 
       }} 
      }; 

      XDocument serviceXml = XDocument.Parse(header); 

      XElement mapping = (XElement)serviceXml.FirstNode; 
      foreach(Product product in Product.products) 
      { 
       XElement newProduct = new XElement("class"); 
       mapping.Add(newProduct); 

       newProduct.Add(new object[] { 
        new XAttribute("name",product.Name), 
        new XAttribute("table","Product"), 
        new XElement("id", new object[] { 
         new XAttribute("name", product.Id), 
         new XAttribute("column", product.Id), 
         new XAttribute("type","int"), 
         new XElement("generator", new XAttribute("class","native")) 
        }), 
        new XElement("property", new object[] { 
         new XAttribute("name","Name"), 
         new XAttribute("column", "Name"), 
         new XAttribute("type","string") 
        }) 
       }); 
       XElement services = new XElement("class", new object[] { 
        new XAttribute("name", "Service"), 
        new XAttribute("table", "Service") 
       }); 
       newProduct.Add(services); 

       foreach (Service service in product.Services) 
       { 
        services.Add(new XElement("id", new object[] { 
         new XAttribute("name", service.Name), 
         new XAttribute("column", service.Id), 
         new XAttribute("type", "int"), 
         new XElement("generator", new XAttribute("class","native")) 
        })); 
       } 
      } 
     } 
    } 
    public class Product 
    { 
     public static List<Product> products = new List<Product>(); 
     public virtual int Id { get; set; } 
     public virtual string Name { get; set; } 
     public virtual IList<Service> Services { get; set; } 
    } 
    public class Service 
    { 
     public virtual int Id { get; set; } // bit values: 1, 2, 4, 8, ... 
     public virtual string Name { get; set; } 
    } 
} 
+0

我的目标是能够调用ISession.Load()方法从数据库返回我的Product对象。本产品只能根据数据库字段中的整数值选择列表中的服务。我没有看到你的答案可以让我在那里。 – DanHarrigan

相关问题