2013-03-14 31 views
2

我試圖使用公式來映射ICollection類型的屬性,但無論使用哪種方法來確定映射中的類型,nHibernate都會引發錯誤。將公式映射到IEnumerable的代碼

No parameterless constructor defined for this object.

這裏是映射文件

this.Property(
    x => x.AllChildIds, 
    m => 
    { 
     m.Type<NHibernate.Type.ListType>(); 
     m.Access(Accessor.Field); 
     m.Formula(@"(WITH [Child] ([Id], [ParentId]) 
      AS (SELECT [hs0].[Id], 
         [hs0].[ParentId] 
       FROM [Client].[dbo].[HierarchySet] [hs0] (NOLOCK) 
       WHERE [hs0].[ParentId] IN (SELECT [hs1].[Id] 
            FROM [Client].[dbo].[HierarchySet] [hs1] (NOLOCK) 
            WHERE [hs1].[Id] = Id /* @p0 */) 
       UNION ALL 


       SELECT [Children].[Id], 
         [Children].[ParentId] 
       FROM [Client].[dbo].[HierarchySet](NOLOCK) AS [Children] 
         JOIN [Child] 
         ON [Children].[ParentId] = [Child].[Id]) 


     SELECT [Child].[Id] 
     FROM [Child] 
    )"); 
}); 

這裏是我的課

private readonly ICollection<long> allChildIds; 
public virtual IEnumerable<long> AllChildIds { get { return this.allChildIds; } } 

如果我更改映射文件類型

m.Type<NHibernate.Type.GenericListType<NHibernate.Type.Int64Type>>();

然後我得到一個Could not determine type for: System.Collections.Generic.IEnumerable錯誤

我知道SQL很複雜,但肯定不應該影響它?

編輯我的NHibernate會話配置

private static Configuration ConfigureNHibernate() 
{ 
    var configration = new Configuration(); 

    configration.SessionFactoryName("SessionFactoryName"); 
    configration.DataBaseIntegration(db => 
            { 
             db.Dialect<MsSql2005Dialect>(); 
             db.Driver<SqlClientDriver>(); 

             db.IsolationLevel = IsolationLevel.ReadUncommitted; 
             db.ConnectionStringName = "database"; 
             db.BatchSize = 20; 
             db.KeywordsAutoImport = Hbm2DDLKeyWords.AutoQuote; 
            }); 

    if (ConfigurationManager.AppSettings["nhibernate-cache"] != null) 
    { 
    configration.Cache(
         x => 
         { 
          x.DefaultExpiration = 300; 
          x.UseMinimalPuts = true; 
          x.RegionsPrefix = "client-"; 
          x.Provider<SysCacheProvider>(); 
          x.UseQueryCache = true; 
         }); 
    } 

    var mapper = new ModelMapper(); 
    mapper.AddMappings(typeof(MessageInMap).Assembly.GetTypes()); 
    var domainMapping = mapper.CompileMappingForAllExplicitlyAddedEntities(); 

    configration.AddMapping(domainMapping); 

    configration.AddAuxiliaryDatabaseObject(new SimpleAuxiliaryDatabaseObject(@" 
          CREATE VIEW [Children] 
          AS 
          WITH [Child] ([Id], [ParentId]) 
          AS (
            SELECT 
              [hs0].[Id], 
              [hs0].[ParentId] 
            FROM 
              [isnapshot.Client].[dbo].[HierarchySet] (NOLOCK) AS [hs0] 

            UNION ALL 

            SELECT 
              [Children_].[Id], 
              [Children_].[ParentId] 
            FROM 
              [isnapshot.Client].[dbo].[HierarchySet] (NOLOCK) AS [Children_] 
            JOIN [Child] ON [Children_].[ParentId] = [Child].[Id] 
          ) 
          GO", "DROP VIEW [Children]")); 

    return configration; 
} 
+0

會發生什麼事,如果你省略類型規範?根據[文檔](http://nhforge.org/doc/nh/en/index.html#mapping-declaration-property),這應該沒問題:「如果你不指定類型,NHibernate將使用反射在命名屬性上對正確的NHibernate類型進行猜測。「 – bigge

+0

如果我沒有指定類型錯誤更改爲ICollection'無法確定類型爲:System.Collections.Generic.ICollection' – JConstantine

+0

好的,那很不幸。你是否試過排除查詢是問題的一部分?它是否適用於相當簡單的查詢(具有相同或不同的結果類型) – bigge

回答

1

你需要把它映射爲集(袋,列表等)成分,而不是財產。然後使用子選擇來獲取它。

我的第一個假設是它映射如下

c.Set(m => m.ChildrenIds, 
    x => 
     { 
      x.Access(Accessor.Field); 
      x.Key(k => k.Column("ParentId")); 
      x.Subselect(@"WITH [Child] ([Id], [ParentId]) 
AS 
(
    SELECT 
     [hs0].[Id], 
     [hs0].[ParentId] 
    FROM 
     [HierarchySet] (NOLOCK) AS [hs0] 

    UNION ALL 

    SELECT 
     [Children].[Id], 
     [Children].[ParentId] 
    FROM 
     [HierarchySet] (NOLOCK) AS [Children] 
    JOIN 
     [Child] ON [Children].[ParentId] = [Child].[Id] 
) 

SELECT * 
FROM [Child]"); 
     }, 
    x => x.Element(e => e.Column("Id"))); 

但是它不工作,因爲WITH條款並不想成爲裏面的子查詢中。生成的查詢:

SELECT 
    childrenid0_.ParentId as ParentId0_, 
    childrenid0_.Id as Id0_ 
FROM (WITH [Child] ([Id], [ParentId]) 
AS 
(
    SELECT 
     [hs0].[Id], 
     [hs0].[ParentId] 
    FROM 
     [HierarchySet] (NOLOCK) AS [hs0] 

    UNION ALL 

    SELECT 
     [Children].[Id], 
     [Children].[ParentId] 
    FROM 
     [HierarchySet] (NOLOCK) AS [Children] 
    JOIN 
     [Child] ON [Children].[ParentId] = [Child].[Id] 
) 

SELECT * 
FROM [Child]) childrenid0_ 
WHERE [email protected];@p0 = 2 [Type: Int32 (0)] 

所以在這種情況下,唯一的解決方案 - 創建一個視圖,並映射到它。

數據庫對象添加到配置

configuration.AddAuxiliaryDatabaseObject(new SimpleAuxiliaryDatabaseObject(@" 
    CREATE VIEW [Children] 
    AS 
    WITH [Child] ([Id], [ParentId]) 
    AS (
     SELECT 
      [hs0].[Id], 
      [hs0].[ParentId] 
     FROM 
      [HierarchySet] (NOLOCK) AS [hs0] 

     UNION ALL 

     SELECT 
      [Children].[Id], 
      [Children].[ParentId] 
     FROM 
      [HierarchySet] (NOLOCK) AS [Children] 
     JOIN [Child] ON [Children].[ParentId] = [Child].[Id] 
    ) 

    SELECT * 
    FROM [Child]", "DROP VIEW [Children]")); 

如果您正在使用的SchemaExport/SchemaUpdate工具的功能來創建/更新你的數據庫模式 - NHibernate的將創建視圖。 如果您沒有使用SchemaExport/SchemaUpdate功能,那麼您需要手動創建視圖。

CREATE VIEW [Children] 
AS 
    WITH [Child] ([Id], [ParentId]) 
    AS (
     SELECT 
      [hs0].[Id], 
      [hs0].[ParentId] 
     FROM 
      [HierarchySet] (NOLOCK) AS [hs0] 

     UNION ALL 

     SELECT 
      [Children].[Id], 
      [Children].[ParentId] 
     FROM 
      [HierarchySet] (NOLOCK) AS [Children] 
     JOIN [Child] ON [Children].[ParentId] = [Child].[Id] 
    ) 

    SELECT * 
    FROM [Child] 

映射:

c.Set(m => m.ChildrenIds, 
    x => 
     { 
      x.Access(Accessor.Field); 
      x.Key(k => k.Column("ParentId")); 
      x.Table("Children"); // or x.Subselect("select * from Children") 
     }, 
    x => x.Element(e => e.Column("Id"))); 
+0

這似乎是一個有效的解決方案,但是在檢索結果時很難找到視圖。我試過在映射中指定模式,並在數據庫名稱前加上了創建視圖。當我嘗試訪問這個字段時,它說未能初始化集合,''無效的對象名稱'Children'。「'創建視圖到底在哪裏? – JConstantine

+0

非常奇怪,因爲它適用於我:(在我的情況下,視圖是在 .dbo。schema下創建的。 – hazzik

+0

你可以嘗試用'x.Subselect(「select * from Children「)'? – hazzik

相關問題