2014-09-23 104 views
1

情況

我有一個通過NHibernate(3.3.3-SP1)映射的數據庫表。該應用程序在.NET4.0上運行,映射通過FluentNHibernate(1.4.0)完成。NHibernate SaveOrUpdate沒有主鍵

CREATE TABLE Movies 
(id INT PRIMARY KEY, 
yearPublished DATETIME NOT NULL, 
name NVARCHAR(500) NOT NULL, 
description NTEXT NOT NULL) 

的數據將是這樣的:

 
id | yearPublished | name     | description 
---+---------------+------------------------+-------------------------------------------- 
1 | 1968   | 2001: A Space Oddyssey | An epic drama of adventure and exploration 

的問題

我創建此表的新的實體,並希望避免增加一個以上的實體相同的實世界的事情。我知道有Session.SaveOrUpdate,也有一種方法可以使它與複合和自然ID一起工作,但那不是我想要的,因爲我的實體實際上有一個主鍵,而且我確實只需要組合鍵就可以確保沒有重複項在數據庫中。

var movie = new Movies 
{ 
    yearPublished = 1968, 
    name = "2001: A Space Oddyssey", 
    description = "An awesome journey to Jupiter" 
}; 

// Behavior right now: 

// Adds a new movie besides the fact that 
// the movie is already in the database 
// but now has two entries 
session.SaveOrUpdate(movie); 

Assert.IsTrue(movie.id == 2 && movie.description == "An awesome journey to Jupiter"); 

// What I really want is to be able to define what 
// makes an object unique other than the primary key; 
// in this scenario it should look for a combination 
// of "yearPublished" and "name" 
session.MyAwesomeSaveOrUpdate(movie); 

Assert.IsTrue(movie.id == 1 && movie.description == "An epic drama of adventure and exploration"); 

這是功能性的地方NHibernate的(例如,通過自定義映射),或者我有獲取從DB候選人,並用手做呢?

謝謝!

回答

0

我加入數據庫中的自然鍵字段的唯一約束,並使用異常轉換到SQL Server異常轉換成一個我的應用程序可以處理解決這個問題。

public class SqlServerExceptionConverter : ISQLExceptionConverter 
{ 
    public Exception Convert(AdoExceptionContextInfo adoExceptionContextInfo) 
    { 
     var sqlException = adoExceptionContextInfo.SqlException as SqlException; 
     if (sqlException != null) 
     { 
      // 2601 is unique key, 2627 is unique index; same thing: 
      // http://blog.sqlauthority.com/2007/04/26/sql-server-difference-between-unique-index-vs-unique-constraint/ 
      if (sqlException.Number == 2601 || sqlException.Number == 2627) 
      { 
       // my custom exception 
       return new UniqueKeyException(sqlException.Message, sqlException); 
      } 
     } 
     return adoExceptionContextInfo.SqlException; 
    } 
} 

另一種方法我能想到的是查詢插入之前匹配的記錄數據庫,但是這不是萬無一失,因爲一個記錄可以選擇與您的插入之間插入。

+0

我真的不使用控制流異常的粉絲,但至少它似乎工作。儘管如此,我一直在使用DIY方法 – mfeineis 2017-04-21 22:44:59

+1

如果您想處理數據庫異常,則沒有其他選擇。您可以通過預先檢查數據或包含where子句來避免它們,但是捕獲異常並將其轉換爲應用程序可以處理的是唯一的萬無一失的方法。 – 2017-04-22 17:27:28