2017-02-09 14 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ファイルの>部分。

--EDIT--

最終的に、私は私の製品モデルを取り戻すためのロード()メソッドを呼び出すことができるようにしたいです。

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

私の目標は、データベースからProductオブジェクトを返すためにISession.Load()メソッドを呼び出せるようにすることです。この製品は、データベースフィールドの整数値に基づいて選択されたリスト内のサービスのみを保持します。私はあなたの答えがそこに私を得ることができる方法を見ていない。 – DanHarrigan

関連する問題