Поделиться через


Модель данных (платформа служб данных ADO.NET)

Службы данных ADO.NET изначально поддерживают модели ADO.NET Entity Framework, платформа и предоставляют расширение, благодаря которому модель данных можно определить с помощью объектов среды CLR. Для описания данных, развертываемых платформой служб данных ADO.NET, используется терминология модели EDM, а именно язык определения концептуальной схемы (CSDL) и такие термины, как EntitySet, EntityType, Property, Association, AssociationSet и т. д. Определение этих терминов см. в разделе Терминология платформы служб данных ADO.NET. Дополнительные сведения о языке CSDL см. в разделе Спецификации модели EDM.

Описывая источники данных с помощью одной грамматики и стандартных соглашений URI, службы данных ADO.NET могут развертывать согласованные представления данных вне зависимости от базового источника данных. При использовании модели Entity Framework настройка службы данных является тривиальной задачей. Для моделей на основе среды CLR определено сопоставление между объектами CLR и типами EDM.

Модель данных EDM

В модели данных EDM службы данных ADO.NET взаимодействуют с уровнем служб объектов платформы Entity Framework — контекстом, программируемым с помощью средств CLR. Хотя контекст программирования и концептуальную модель можно создать вручную, рекомендуется использовать средства Средства работы с моделью EDM, входящие в состав среды Microsoft Visual Studio 2008, начиная с пакета обновления SP1.

Пример использования средств EDM и Entity Framework см. в разделе Краткое руководство по службе данных (платформа служб данных ADO.NET).

Модель данных на основе CLR

Работа служб данных ADO.NET осуществляется путем преобразования запросов URI в операции над данными, которые адресуются синтаксисом URI. Если модель данных основана на платформе Entity Framework, URI преобразуются в вызовы методов служб объектов. Контекст объектов ObjectContext Entity Framework развертывает наборы данных на основе шаблона ObjectQuery<T>, а ObjectQuery<T> реализует интерфейс IQueryable<T>.

Любая технология или поставщик данных, развертывающий данные путем наследования от интерфейса IQueryable, можно развернуть в качестве службы данных ADO.NET. Метод расширения AsQueryable, доступный начиная с платформы .NET Framework версии 3.5, можно использовать с объектами, реализующими интерфейс IEnumerable<T>. Все классы платформы .NET Framework, реализующие интерфейс IEnumerable<T>, можно расширить, вызвав метод расширения AsQueryable. Это значит, что большинство списков, массивов и коллекций можно эффективно развернуть в качестве служб данных ADO.NET.

Запросы LINQ также работают с источниками данных, которые реализуют интерфейс IEnumerable<T> или IQueryable<T>. При задании базовой модели данных для служб данных ADO.NET с использованием объектов CLR запросы URI преобразуются в запросы LINQ. Между объектами CLR и ресурсами служб данных ADO.NET определено полное сопоставление. Сопоставление объектов CLR с наборами сущностей ADO.NET позволяет службам данных выполнять развертывание любых источников данных, которые можно считать в память в качестве массива, списка или коллекции.

Пример 1: сопоставление классов CLR с ресурсами служб данных ADO.NET

В следующем примере демонстрируется полное сопоставление между конструкциями CLR и ресурсами служб данных ADO.NET. Классы, реализующие интерфейс IQueryable<T>, представлены как наборы сущностей.

В следующем примере метод расширения AsQueryable используется для преобразования массива Customers в формат IQueryable<T>. Массив Customers в этом примере имеет простую структуру, но данные приложения можно считать из практически любого источника.

Пример кода сопровожден пояснениями, описывающими сопоставление типов CLR с типами ресурсов служб данных ADO.NET.

namespace Accounting  // Namespace
{
    public class DataModel  // EntityContainer
    {
        public IQueryable<Customer> Customers  // EntitySet
        {
            get
            {
                return new Customer[] { new Customer(1, "name1"),
                               new Customer(2,
                              "name2") }.AsQueryable<Customer>();
            }
        }
    }

    public class Customer  // EntityType
    {
        private int _ID;
        private string _name;
        private Address _address;

        public Customer(int i, string name)
        {
            _ID = i;
            _name = name;
            _address.Line1 = "Line" + i;
            _address.Line2 = "Line" + i;
        }

        [DataWebKeyAttribute]
        public int ID  // Entity Type Key
        {
            get { return _ID; }
        }

        public string CustName   // Property
        {
            get { return _name; }
        }

        public Address Address   // Property
        {
            get { return _address; }
        }

    }


    public struct Address   // ComplexType
    {
        private string line1;
        private string line2;

        public string Line1   // Property
        {
            get { return this.line1; }
            set { this.line1 = value; }
        }

        public string Line2   // Property
        {
            get { return this.line2; }
            set { this.line2 = value; }
        }
    }
}

При сопоставлении сущности CLR с ресурсом служб данных ADO.NET регистр имени CLR копируется связанным ресурсом служб данных ADO.NET. Типы CLR, соответствующие ресурсам служб данных ADO.NET, как указано в комментариях в предыдущем коде, описаны в следующем списке.

Контейнеры сущностей и наборы сущностей

  • Для определения всех наборов сущностей верхнего уровня в модели используется один открытый класс CLR (C1), находящийся в явно заданном пространстве имен. Доступ к ресурсам верхнего уровня можно получить с помощью первого сегмента пути в URI.

  • Пространство имен, в котором существует класс C1 — это пространство имен, которое определяет C1 как контейнер сущностей. Это неизменно даже в том случае, если C1 — производный тип.

  • Имя класса C1 представляет контейнер сущностей. Для пространства имен можно определить только один контейнер сущностей. Это неизменно даже в том случае, если C1 — производный тип.

  • Каждый набор сущностей должен быть представлен как открытое свойство (P1) класса C1 с типом возвращаемого значения IQueryable<T>. В классе C1 или в одном из его родительских классов может присутствовать любое количество подобных свойств.

    • T представляет тип сущности в наборе сущностей.

    • В типе T должно присутствовать свойство, которое можно использовать как ключ сущности, чтобы свойство C1 можно было рассматривать в качестве набора сущностей. Если такого ключевого свойства нет, свойство P1 пропускается, а C1 не рассматривается службой данных ADO.NET как набор сущностей.

    • Один и тот же тип T не может возвращаться более чем одним свойством класса C1 или его родительского класса. Это определение модели на основе CLR не поддерживает включение одного и того же типа сущности, представленного в этом случае классом T, в несколько наборов сущностей. Множественные наборы сущностей для одного типа можно реализовать в платформе Entity Framework, но не в качестве классов, развертываемых как службы данных ADO.NET.

Типы сущностей, свойства и ссылки навигации

  • Открытый класс CLR (C1) представляет тип сущности.

  • Чтобы тип распознавался как тип сущности, в классе должно присутствовать одно или несколько свойств, представляющих ключ типа. Такое свойство или группа свойств становится ключом (или ключами) для типа сущности. Правила для свойств, представляющих ключ:

    • Открытое свойство с именем ID.

    • Открытое свойство с именем <имя_класса>ID.

    • Открытые свойства, отмеченные атрибутом DataWebKeyAttribute.

    • Если класс содержит свойство или группу свойств, отмеченных атрибутом DataWebKeyAttribute, то они используются в качестве ключа, а первые два правила игнорируются. Если нет свойств, отмеченных этих атрибутом, то ключевое свойство типа сущности определяют свойства, удовлетворяющие первым двум правилам. Если правилам удовлетворяют несколько свойств, то у типа сущности по определению составной ключ.

  • Если класс C1 является частью иерархии, иерархия классов преобразуется в иерархию типов сущностей с применением следующих правил:

    • Класс CLR, ближайший к корню иерархии классов, включающий допустимое ключевое свойство, становится корнем иерархии типов сущностей. Если класс C1 не является корнем иерархии классов CLR, в которой он участвует, то свойства, объявленные в классах, находящихся в иерархии выше C1, считаются объявленными в C1.
  • Каждое свойство (P), объявленное в классе C1, преобразуется в свойство в типе сущностей, если свойство CLR удовлетворяет всем следующим соглашениям:

    • Свойство CLR должно иметь открытую область видимости.

    • Свойство CLR должно реализовывать метод get свойства.

    • Свойство CLR не должно быть индексатором.

    • Если тип возвращаемого значения свойства P — примитивный, и этот тип соответствует типу EDM, свойство должно быть представлено как свойство. Описание сопоставления типов EDM с типами CLR см. в разделе Типы содержимого служб данных ADO.NET.

    • Если тип возвращаемого значения свойства P — ссылочный, и сам этот тип или один из его родительских типов, если это производный тип, представляет тип сущности, то P представляет ссылку навигации (1–1).

    • Если тип возвращаемого значения свойства P — IEnumerable<T>, и класс T представляет тип сущности, то P представляет ссылку навигации «один ко многим».

    • Если тип возвращаемого значения свойства P — тип значения, то P представляет сложный тип.

Сложные типы

  • Открытый тип значения CLR (V1) представляет сложный тип.

  • Каждое свойство типа значения V1 преобразуется в свойство сложного типа. При определении сопоставления свойства CLR со свойством сложные типы подчиняются тем же правилам, что и типы сущности.

    • Свойство CLR должно иметь открытую область видимости.

    • Свойство CLR должно реализовывать метод get свойства.

    • Свойство CLR не должно быть индексатором.

    • Если тип возвращаемого значения свойства P — ссылочный, и сам этот тип или один из его родительских типов, если это производный тип, представляет тип сущности, то P представляет ссылку навигации (один к одному).

Пример 2: сопоставление классов CLR с ресурсами служб данных ADO.NET

В следующем примере показаны классы CLR, включающие наследование, используемое для реализации типов ресурсов служб данных ADO.NET.

namespace Accounting
{
    public class DataModel
    {
        public IQueryable<Customer> Customers
        {
            get
            {
                return new Customer[] { new Customer(1, "name1"),
                    new Customer(2, "name2") }.AsQueryable<Customer>();
            }
        }

        public IQueryable<Order> Orders
        {
            get
            {
                return new Order[] { new Order(1, "order1"),
                   new Order(2, "order2") }.AsQueryable<Order>();
            }
        }
    }


    public class DerivedDataModel : DataModel
    {
        public IQueryable<HumanResources.Employee> Employees
        {
            get { return new HumanResources.Employee[] { new 
                        HumanResources.Employee(1, "EmpName1"), new 
                        HumanResources.Employee(2, "EmpName2") 
                         }.AsQueryable<HumanResources.Employee>(); 
               } 
        }
    }

    public class Person
    {
        protected int _ID;
        public Person() { }
        public Person(int i)
        {
            _ID = i;
        }

        [DataWebKeyAttribute]
        public int ID
        {
            get { return _ID; }
        }
    }

    public class Customer : Person
    {
        private string _name;
        private Address _address;
        List<Order> _orders;

        public Customer(int i, string name)
        {
            _ID = i;
            _name = name;
            _orders = new List<Order>();
            if (i == 1) { _orders.Add(new Order(1, "order1")); }
            if (i == 2) { _orders.Add(new Order(2, "order2")); }
            _address.Line1 = "Line" + i;
            _address.Line2 = "Line" + i;
        }

        public string CustName
        {
            get { return _name; }
        }

        public Address Address
        {
            get { return _address; }
        }

        public IList<Order> Orders
        {
            get { return _orders; }
        }
    }

    public class Order
    {
        private int _ID;
        private string _name;

        public Order(int i, string name)
        {
            _ID = i;
            _name = name;
        }

        [DataWebKeyAttribute]
        public int OrderKey
        {
            get { return _ID; }
        }

        public string OrderName
        {
            get { return _name; }
        }
    }

    public struct Address
    {
        private string line1;
        private string line2;

        public string Line1
        {
            get { return this.line1; }
            set { this.line1 = value; }
        }

        public string Line2
        {
            get { return this.line2; }
            set { this.line2 = value; }
        }
    }
}

namespace HumanResources
{
    public class Employee
    {
        private int _ID;
        private string _name;

        public Employee(int i, string name)
        {
            _ID = i;
            _name = name;
        }

        public int ID
        {
            get { return _ID; }
        }

        public string EmpName
        {
            get { return _name; }
        }
    }
}

Поддержка записи и обновления

Для поддержки создания, обновления и удаления в модели данных CLR класс, моделирующий наборы сущностей верхнего уровня, должен реализовывать интерфейс IUpdatable. В примере 2 «Сопоставление объектов CLR с ресурсами служб данных ADO.NET» класс Accounting.DataModel должен реализовать интерфейс IUpdatable.

См. также

Понятия

Спецификации служб данных ADO.NET

Другие ресурсы

Модель EDM