2016-04-26 62 views
0

我正在使用NHibernate和流利NHibernate进行映射的.NET Web API应用程序。是否有可能从标量函数的结果中分配默认值

我有一个名为标量函数“next_photo_id()”产生像 Sharding & IDs at Instagram

Int64的数量,但我不能指定标量函数MySQL中的默认值ID列。我试过了,我得到了错误。

ALTER TABLE `photos` 
    CHANGE COLUMN `id` `id` BIGINT(20) NOT NULL DEFAULT next_photo_id() FIRST ; 

所以我试着从应用程序端使用fluentNhibernate分配Id。

我的照片表的类映射是

public class PhotoMap : ClassMap<Photo> 
{ 
    public PhotoMap() 
    { 
     Table("photos"); 


     Id(m => m.Id).Column("id").Access.Property().Default("next_photo_id()"); 

     Map(m => m.Caption).Column("caption"); 
    } 
} 

照片表插入查询必须是,

Insert Into photos (id,caption) values (next_photo_id(),"test") 

但我不能这样做。无论如何去做?

回答

1

在映射中定义默认值仅适用于DDL。所以基本上,你刚刚告诉NHibernate尝试定义默认的SQL约束,以防你要求它为你生成数据库模式。 (这将与您尝试直接在SQL中定义的那个相同)。

对于您的情况,您需要定义自定义插入查询。我知道如何使用的hbm.xml映射做到这一点,它记录here,它会是这样的:

<class name="PhotoMap" table="photos"> 
    ... 

    <sql-insert>insert into photos (caption, id) 
     values (?, 
     case when ? is null then next_photo_id() else next_photo_id() end) 
    </sql-insert> 
</class> 

如记录,你应该首先确定以何种顺序NHibernate的发送其参数,并坚持这一顺序。此外,NHibernate会期望id的位置参数,如果没有它,将会失败。所以我用case解决它。您可以通过使用存储过程接受所有参数来更加干净地处理这个问题,并且哪一个主体会忽略id之一。

对于翻译这到流利NHibernate,我不知道,我不使用它。

您现在仍然有一个重大障碍需要克服:您应该使用什么发电机作为您的ID字段?我没有看到任何合适的东西。你可能对NHibernate说谎,并告诉它类似assigned,但它不会为你检索在db端生成的id。你必须清除会话,并查询你新添加的照片,如果你有一些自然ID找到它...

否则,你必须实施custom id generator支持你的情况。它应该是靠近身份的东西。但要小心,这一个,as documented,导致sql-insert被忽略。实施自定义生成器时可能会遇到同样的问题。

如果您id是一个简单的属性,而不是实体ID,你可以简单地告诉NHibernate的是generated

<property name="Id" generated="insert" /> 

但对于ID,如上所述,这是方式较为复杂,只要我知道。

数据库端

您的默认值应该可以在db中执行。与SQL Server,定义默认会像一个正确的方法:

alter table photos add constraint DefPhotosId default (dbo.next_photo_id()) for Id 

如果在试图定义默认出现你的错误你应该打开一个MySQL的问题。

但无论如何,你仍然会在NHibernate端有id生成器的麻烦。

相关问题