【问题标题】:NHibernate SaveOrUpdate without primary keyNHibernate SaveOrUpdate 没有主键
【发布时间】:2014-11-17 17:03:09
【问题描述】:

情况

我有一个通过 NHibernate (3.3.3-SP1) 映射的数据库表。该应用程序在 .NET4.0 上运行,并且通过 FluentNHibernate (1.4.0) 完成映射。

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

数据会是这样的:

编号 |年发表 |姓名 |描述 ---+---------------+------------+-- -------------------------------------- 1 | 1968 | 2001:太空漫游|一部史诗般的冒险和探索剧

问题

我正在创建此表的新实体,并希望避免为同一个现实世界的事物添加多个实体。我知道有 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 中是否存在(例如,通过自定义映射)还是我已经从数据库中获取候选人并手动完成?

谢谢!

【问题讨论】:

    标签: nhibernate orm entity composite-key


    【解决方案1】:

    我通过在数据库中的自然键字段上添加唯一约束并使用异常转换器将 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;
        }
    }
    

    我能想到的另一种方法是在插入之前查询数据库以获取匹配记录,但这并不是万无一失的,因为可以在选择和插入之间插入一条记录。

    【讨论】:

    • 我不太喜欢在控制流中使用异常,但至少它似乎有效。虽然,我最后一直用DIY的方法
    • 如果您想处理数据库异常,没有其他选择。您可以尝试通过预先检查数据或包含 where 子句来避免它们,但捕获异常并将其转换为您的应用程序可以处理的东西是唯一万无一失的方法。
    猜你喜欢
    • 1970-01-01
    • 2010-12-09
    • 1970-01-01
    • 2013-03-26
    • 2017-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多