NHibernate 3.2 по коду ClassMapping для свойства версии - PullRequest
5 голосов
/ 02 декабря 2011

Как правильно отобразить столбец метки времени в базе данных SQL Server 2008 с использованием новых сопоставлений на основе кода NHibernate?

У меня есть свойство в моем классе, определенное как byte [], и я использую свойствоследующее отображение в моем файле ClassMapping:

Version(x => x.RowVersion, mapping =>
   mapping.Generated(VersionGeneration.Always));

Однако NHibernate ожидает целое число, основанное на этом отображении (выдает исключение при вставках).Если я явно указываю тип отображения как byte [], я получаю исключение, в котором говорится: «System.ArgumentOutOfRangeException: ожидаемый тип, реализующий IUserVersionType Имя параметра: persistentType".

Как правильно отобразить отметку времени автоматического обновлениястолбец с новыми сопоставлениями, основанными на коде NHibernate?

--- EDIT

Я думаю, что я сузил, что мне нужно установить тип сопоставления в BinaryType (тип NHibernate, который реализует типIVersionType), но BinaryType не имеет публичного конструктора ... Я думаю, что у меня нет идей.

Ответы [ 3 ]

5 голосов
/ 27 января 2012

Если вы захватите исходный код NHib, в тестовом проекте есть класс, который поможет вам с тем, что вам нужно: NHibernate.Test.VersionTest.Db.MsSQL.BinaryTimestamp. По сути, вы должны дать ему пользовательский тип, который он может использовать для преобразования значения. По умолчанию NHib ожидает, что значение будет int (посмотрите на seciont 5.1.7 из the nhib docs ). Если вы используете int / bigint в качестве столбца версии, вам не понадобится пользовательский тип.

Пользовательский класс (взят из исходного кода NHib):

public class BinaryTimestamp : IUserVersionType
{
    #region IUserVersionType Members

    public object Next(object current, ISessionImplementor session)
    {
        return current;
    }

    public object Seed(ISessionImplementor session)
    {
        return new byte[8];
    }

    public object Assemble(object cached, object owner)
    {
        return DeepCopy(cached);
    }

    public object DeepCopy(object value)
    {
        return value;
    }

    public object Disassemble(object value)
    {
        return DeepCopy(value);
    }

    public int GetHashCode(object x)
    {
        return x.GetHashCode();
    }

    public bool IsMutable
    {
        get { return false; }
    }

    public object NullSafeGet(IDataReader rs, string[] names, object owner)
    {
        return rs.GetValue(rs.GetOrdinal(names[0]));
    }

    public void NullSafeSet(IDbCommand cmd, object value, int index)
    {
        NHibernateUtil.Binary.NullSafeSet(cmd, value, index);
    }

    public object Replace(object original, object target, object owner)
    {
        return original;
    }

    public System.Type ReturnedType
    {
        get { return typeof(byte[]); }
    }

    public SqlType[] SqlTypes
    {
        get { return new[] { new SqlType(DbType.Binary, 8) }; }
    }

    public int Compare(object x, object y)
    {
        var xbytes = (byte[])x;
        var ybytes = (byte[])y;
        return CompareValues(xbytes, ybytes);
    }

    bool IUserType.Equals(object x, object y)
    {
        return (x == y);
    }

    #endregion

    private static int CompareValues(byte[] x, byte[] y)
    {
        if (x.Length < y.Length)
        {
            return -1;
        }
        if (x.Length > y.Length)
        {
            return 1;
        }
        for (int i = 0; i < x.Length; i++)
        {
            if (x[i] < y[i])
            {
                return -1;
            }
            if (x[i] > y[i])
            {
                return 1;
            }
        }
        return 0;
    }

    public static bool Equals(byte[] x, byte[] y)
    {
        return CompareValues(x, y) == 0;
    }
}

Пример отображения с использованием этого класса:

public class Car
{
    public virtual long CarId { get; set; }
    public virtual string Name { get; set; }
    public virtual byte[] LastModified { get; set; }

    public override string ToString()
    {
        return string.Format("Id: {0}, Name: {1}, Last Modified: {2}", CarId, Name, LastModified);
    }
}

public class CarMap : ClassMapping<Car>
{
    public CarMap()
    {
        Table("Cars");

        Id(car => car.CarId, mapper => mapper.Generator(Generators.Identity));
        Property(car => car.Name);
        Version(car => car.LastModified, mapper =>
                                             {
                                                 mapper.Generated(VersionGeneration.Always);
                                                 mapper.Type<BinaryTimestamp>();
                                             });
    }
}
4 голосов
/ 02 декабря 2011

Мы также используем byte[] Version { get; } для реализации версии.

Здесь приведены сопоставления:

Version(x => x.Version)
            .Nullable()
            .CustomSqlType("timestamp")
            .Generated.Always()
            ;

Также для получения более подробной информации см. эту ссылку

3 голосов
/ 22 августа 2013

В случае ConventionModelMapper я использовал следующее ..

ConventionModelMapper mapper = new ConventionModelMapper();

//...other mappings

mapper.Class<Entity>(map => map.Version(e => e.Revision, m =>
                {
                    m.Generated(VersionGeneration.Always);
                    m.UnsavedValue(null);
                    m.Type(new BinaryBlobType());
                    m.Column(c =>
                        {
                            c.SqlType("timestamp");
                            c.NotNullable(false);
                        });
                }));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...