Сообщений 0    Оценка 165        Оценить  
Система Orphus

Как использовать фабрику объектов для чтения объектов разных типов из базы данных

Business Logic Toolkit

Автор: Igor Tkachev
The RSDN Group
Опубликовано: 26.03.2006
Исправлено: 15.04.2009
Версия текста: 1.0

Проект BLToolkit

Для чтения объектов разных типов из одного источника данных может использоваться фабрика объектов - возможность, предоставляемая классом TypeAccessor. Метод CreateInstanceEx класса TypeAccessor всегда перед созданием экземпляра объекта проверяет значение свойства ObjectFactory и если оно не равно null, то управление создания объекта передаётся фабрике ассоциированной со свойством ObjectFactory. Свойство ObjectFactory может быть проинициализировано либо вручную в начале выполнения программы, либо, как следующем примере, с помощью атрибута ObjectFactoryAttribute.

using System;
using System.Collections.Generic;

using NUnit.Framework;

using BLToolkit.Data;
using BLToolkit.Mapping;
using BLToolkit.Reflection;

namespace HowTo.Reflection
{
    [TestFixture]
    public class ObjectFactoryTest
    {
        [ObjectFactory(typeof(Person.ObjectFactory))]
        public class Person
        {
            [MapField("PersonID")]
            public int    ID;

            public string LastName;
            public string FirstName;
            public string MiddleName;

            class ObjectFactory : IObjectFactory
            {
                public object CreateInstance(TypeAccessor typeAccessor, InitContext context)
                {
                    // Get the object type indicator field.
                    //
                    object objectType = context.DataSource.GetValue(context.SourceObject, "PersonType");

                    // Target ObjectMapper must be changed in order to provide correct mapping.
                    //
                    switch ((string)objectType)
                    {
                        case "D": context.ObjectMapper = ObjectMapper<Doctor>. Instance; break;
                        case "P": context.ObjectMapper = ObjectMapper<Patient>.Instance; break;
                    }

                    // Create an object instance.
                    // Do not call ObjectMapper.CreateInstance as it will lead to infinite recursion.
                    //
                    return context.ObjectMapper.TypeAccessor.CreateInstance(context);
                }
            }
        }

        public class Doctor : Person
        {
            public string Taxonomy;
        }

        public class Patient : Person
        {
            public string Diagnosis;
        }

        [Test]
        public void Test()
        {
            using (DbManager db = new DbManager())
            {
                List<Person> list = db
                    .SetCommand(@"
                        SELECT
                            ps.*,
                            d.Taxonomy,
                            p.Diagnosis,
                            CASE
                                WHEN d.PersonID IS NOT NULL THEN 'D'
                                WHEN p.PersonID IS NOT NULL THEN 'P'
                            END as PersonType
                        FROM
                            Person ps
                                LEFT JOIN Doctor  d ON d.PersonID = ps.PersonID
                                LEFT JOIN Patient p ON p.PersonID = ps.PersonID
                        ORDER BY
                            ps.PersonID")
                    .ExecuteList<Person>();

                Assert.AreEqual(list[0].GetType(), typeof(Doctor));
                Assert.AreEqual(list[1].GetType(), typeof(Patient));

                if (list.Count > 2)
                    Assert.AreEqual(list[2].GetType(), typeof(Person));
            }
        }
    }
}

SQL скрипт для создания базы данных:

--CREATE DATABASE BLToolkitData ON PRIMARY
--(NAME=N'BLToolkitTest',     FILENAME=N'C:\Data\MSSQL.1\MSSQL\DATA\BLToolkitData.mdf',     SIZE=3072KB, FILEGROWTH=1024KB)
--LOG ON 
--(NAME=N'BLToolkitTest_log', FILENAME=N'C:\Data\MSSQL.1\MSSQL\DATA\BLToolkitData_log.ldf', SIZE=1024KB, FILEGROWTH=10%)
--GO

IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID('Doctor') AND type in (N'U'))
BEGIN DROP TABLE Doctor END

IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID('Patient') AND type in (N'U'))
BEGIN DROP TABLE Patient END

-- Person Table

IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID('Person') AND type in (N'U'))
BEGIN DROP TABLE Person END

CREATE TABLE Person
(
	PersonID   int          NOT NULL IDENTITY(1,1) CONSTRAINT PK_Person PRIMARY KEY CLUSTERED,
	FirstName  nvarchar(50) NOT NULL,
	LastName   nvarchar(50) NOT NULL,
	MiddleName nvarchar(50)     NULL,
	Gender     char(1)      NOT NULL CONSTRAINT CK_Person_Gender CHECK (Gender in ('M', 'F', 'U', 'O'))
)
ON [PRIMARY]
GO

INSERT INTO Person (FirstName, LastName, Gender) VALUES ('John',   'Pupkin',    'M')
INSERT INTO Person (FirstName, LastName, Gender) VALUES ('Tester', 'Testerson', 'M')
GO

-- Doctor Table Extension

CREATE TABLE Doctor
(
	PersonID int          NOT NULL
		CONSTRAINT PK_Doctor        PRIMARY KEY CLUSTERED
		CONSTRAINT FK_Doctor_Person FOREIGN KEY
			REFERENCES Person ([PersonID])
			ON UPDATE CASCADE
			ON DELETE CASCADE,
	Taxonomy nvarchar(50) NOT NULL
)
ON [PRIMARY]
GO

INSERT INTO Doctor (PersonID, Taxonomy) VALUES (1, 'Psychiatry')
GO

-- Patient Table Extension

CREATE TABLE Patient
(
	PersonID  int           NOT NULL
		CONSTRAINT PK_Patient        PRIMARY KEY CLUSTERED
		CONSTRAINT FK_Patient_Person FOREIGN KEY
			REFERENCES Person ([PersonID])
			ON UPDATE CASCADE
			ON DELETE CASCADE,
	Diagnosis nvarchar(256) NOT NULL
)
ON [PRIMARY]
GO

INSERT INTO Patient (PersonID, Diagnosis) VALUES (2, 'Hallucination with Paranoid Bugs'' Delirium of Persecution')
GO

App.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>
        <add 
            key   = "ConnectionString"
            value = "Server=.;Database=BLToolkitData;Integrated Security=SSPI"/>
    </appSettings>
</configuration>


Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав.
    Сообщений 0    Оценка 165        Оценить