2017-02-09 37 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

相關問題