Как можно свободно связать столбцы базы данных в приложении .NET? - PullRequest
2 голосов
/ 15 января 2009

У меня есть две версии почти идентичной базы данных. Ниже я создал таблицу примеров, чтобы продемонстрировать основные различия, а именно: столбец идентификатора был изменен с целочисленного идентификатора на GUID, а различные свойства были обновлены, в архиве примера был заменен readOnly и скрыт:

Старая версия:

CREATE TABLE Example
(
    --Data Identity (maps to DbId in the example code)
    Id int IDENTITY PRIMARY KEY,

    --Example columns
    SomeValue varchar(50),
    AnotherValue int,

    --Data Properties
    Archived bit
)

Новая версия:

CREATE TABLE Example
(
    --Data Identity (maps to DbId in the example code)
    Id uniqueidentifier PRIMARY KEY,

    --Example columns
    SomeValue varchar(50),
    AnotherValue int,

    --Data Properties
    ReadOnly bit,
    Hidden bit
)

Мне нужно иметь возможность использовать O / R Mapper, такой как NHibernate, для подключения к одной или другой из этих версий базы данных. Я бы хотел сообщить приложению, какую версию использовать через настройки в файле конфигурации.

Первоначально я планировал создать общий интерфейс для бизнес-логики и использовать контейнер IoC, например Unity, для переключения между соответствующими конкретными классами в файле конфигурации.

Ниже приведен пример кода, который я создал для проверки этой теории:

public interface IDataIdentity
{
    object Id { get; }
}

public class LegacyDataIdentity : IDataIdentity
{
    public virtual long DbId { get; set; }

    public object Id
    {
        get { return DbId; }
    }
}

public class NewDataIdentity : IDataIdentity
{
    public virtual Guid DbId { get; set; }

    public object Id
    {
        get { return DbId; }
    }
}


public interface IDataProperties
{
    bool ReadOnly { get; set; }
    bool Hidden { get; set; }
}

public class LegacyDataProperties : IDataProperties
{
    public virtual bool Archived { get; set; }

    public bool ReadOnly
    {
        get { return Archived; }
        set { Archived = value; }
    }

    public bool Hidden
    {
        get { return Archived; }
        set { Archived = value; }
    }
}

public class NewDataProperties : IDataProperties
{
    public virtual bool ReadOnly { get; set; }
    public virtual bool Hidden { get; set; }
}


public class DataItem
{
    public DataItem(IDataIdentity dataIdentity, IDataProperties dataProperties)
    {
        DataIdentity = dataIdentity;
        DataProperties = dataProperties;
    }

    public IDataIdentity DataIdentity { get; set; }
    public IDataProperties DataProperties { get; set; }
}

public class Example : DataItem
{
    public Example(IDataIdentity dataIdentity, IDataProperties dataProperties)
        : base(dataIdentity, dataProperties)
    {
    }

    public virtual string SomeValue { get; set; }
    public virtual int AnotherValue { get; set; }
}

Кто-нибудь может посоветовать, возможно ли это (особенно с Unity и NHibernate), и если да, то как создать соответствующие файлы сопоставления NHibernate?

В качестве альтернативы, может ли кто-нибудь предложить какое-либо решение проблемы, используя любые другие методы или другие инструменты отображения IoC и O / R (коммерческие или открытые)?

Большое спасибо,

Пол

Ответы [ 3 ]

2 голосов
/ 20 января 2009

Почему бы не абстрагировать своего поставщика данных, реализуя 2 версии (одну с отображениями nhibernate для устаревшего элемента данных и одну для нового элемента данных).

Чтобы перефразировать ваш код (упрощенно для ясности):

public abstract class AbstractData
{
    public abstract string SomeValue { get; set; }
    public abstract bool ReadOnly { get; set; }
    //etc.
}

public interface IDataProvider
{
    AbstractData Get(object id);
}

public class LegacyData : AbstractData
{
     // Implement AbstractData, and
     public virtual long Id { get { return m_Id; } set { m_Id = value; };
     private long m_Id;
}

public class LegacyDataNHibernateProvider : IDataProvider
{
     public LegacyDataProvider()
     {
         // Set up fluent nhibernate mapping 
     }

     public AbstractData Get(object id)
     {
           // Interpret id as legacy identifier, retrieve LegacyData item, and return
     }
};

// Same again for new data provider

Таким образом, вы не привязаны к nhibernate (или к базе данных, в этом отношении), и вы можете указать конкретные классы с правильно типизированными идентификаторами (которые может обрабатывать nhibernate). Это тот подход, который я использую, когда мне необходимо сопоставить SP существующей базы данных, но позже я перенесусь на новую систему на базе ORM.

0 голосов
/ 15 января 2009

Трудно рекомендовать, не зная полной картины, но .... Вы можете создать обструкцию в SP, если SP вернет одинаковый набор данных для обеих структур таблиц.

Другая проблема, о которой я думаю, это то, что вы можете указать разные файлы сопоставления Hybernate и инициализировать Hibernate другим файлом в зависимости от того, к какой базе данных вы подключаетесь.

0 голосов
/ 15 января 2009

Возможно, я не правильно понимаю ваш вопрос, но мне кажется, что вам нужно реализовать что-то вроде "Factory Pattern".

Недавно я использовал фабричный шаблон для кодирования (c #) двух уровней данных, когда компания, в которой я работаю, переключалась с JDE на SAP. Мне удалось переключить переключатель конфигурации, чтобы переключаться между двумя уровнями данных, и графический интерфейс не знал бы ничего другого.

Вот пара ссылок, которые я нашел:

http://msdn.microsoft.com/en-us/library/ms954600.aspx http://www.allapplabs.com/java_design_patterns/factory_pattern.htm http://en.wikipedia.org/wiki/Abstract_factory_pattern

Что касается NHibernate, я не знаком с ним ... извините. Надеюсь, это поможет.

...