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


Как сопоставить связи базы данных (LINQ to SQL)

Обновлен: November 2007

Отношения данных, которые всегда останутся неизменными, можно закодировать в виде ссылок в классе сущностей. В учебной базе данных Northwind, всегда существует связь между заказчиками и их заказами, т.к. обычно заказчики размещают заказы.

LINQ to SQL определяет атрибут AssociationAttribute, с помощью которого представляются такие отношения. Этот атрибут используется вместе с типами EntitySet<TEntity> и EntityRef<TEntity> для представления в базе данных отношения внешнего ключа. Дополнительные сведения см. в подразделе «Атрибут Association» раздела Сопоставление на основе атрибутов (LINQ to SQL).

Bb386950.alert_note(ru-ru,VS.90).gifПримечание.

В значениях свойства Storage для атрибутов AssociationAttribute и ColumnAttribute учитывается регистр. Например, следует убедиться в том, что регистр символов в значении, использованном в атрибуте свойства AssociationAttribute.Storage, соответствует регистру символов в соответствующих именах свойств в остальном коде. Это относится ко всем языкам программирования среды .NET, даже к тем, которые обычно не учитывают регистр, включая Visual Basic. Дополнительные сведения о свойстве Storage см. в разделе DataAttribute.Storage.

Большинство связей имеют тип «один ко многим», как и в примере, представленном далее в этом разделе. Отношения "один-к-одному" и "один-ко-многим" можно представить следующим образом.

  • Один к одному. Этот тип связей представляется включением элементов EntitySet<TEntity> с обеих сторон.

    Например, рассмотрим отношение Customer-SecurityCode, созданное таким образом, что код безопасности клиента не будет найден в таблице Customer, а может быть получен только авторизованными лицами.

  • Многие ко многим. В связях типа «многие ко многим» первичный ключ связанной таблицы (называемой также таблицей соединения) часто формируется составлением внешних ключей из двух других таблиц.

    Например, рассмотрим связь Employee-Project типа «многие ко многим», образованную с помощью связанной таблицы EmployeeProject. Для LINQ to SQL необходимо, чтобы такая связь моделировалась по трем классам: Employee, Project и EmployeeProject. В этом случае изменение отношения между Employee и Project может потребовать обновления первичного ключа EmployeeProject. Однако данная ситуация наилучшим образом моделируется для удаления существующего EmployeeProject и создания нового EmployeeProject.

    Bb386950.alert_note(ru-ru,VS.90).gifПримечание.

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

    С другой стороны, объекты в LINQ to SQL ссылаются друг на друга с помощью ссылок свойств или коллекций ссылок, к которым можно перейти с использованием точечной нотации.

Пример

В следующем примере отношения "один-ко-многим" класс Customer имеет свойство, объявляющее отношение между клиентами и их заказами. Свойство Orders имеет тип EntitySet<TEntity>. Этот тип указывает, что данное отношение относится к виду "один-ко-многим" (один клиент — много заказов). Свойство OtherKey используется для описания установки данной связи, а именно: путем указания в связанном классе имени свойства, которое будет сравниваться с существующим. В этом примере свойство CustomerID сравнивается таким образом, как если бы соединение базы данных сравнивалось с данным значением столбца.

Bb386950.alert_note(ru-ru,VS.90).gifПримечание.

Если разработка ведется в среде Visual Studio, можно использовать Сред. Объектно-реляционный конструктор для создания ассоциации между классами.

<Table(Name:="Customers")> _
Public Class Customer
    <Column(IsPrimaryKey:=True)> _
Public CustomerID As String
    ' ...
    Private _Orders As EntitySet(Of Order)
    <Association(Storage:="_Orders", OtherKey:="CustomerID")> _
    Public Property Orders() As EntitySet(Of Order)
        Get
            Return Me._Orders
        End Get
        Set(ByVal value As EntitySet(Of Order))
            Me._Orders.Assign(value)
        End Set
    End Property
End Class
[Table(Name = "Customers")]
public partial class Customer
{
    [Column(IsPrimaryKey = true)]
    public string CustomerID;
    // ...
    private EntitySet<Order> _Orders;
    [Association(Storage = "_Orders", OtherKey = "CustomerID")]
    public EntitySet<Order> Orders
    {
        get { return this._Orders; }
        set { this._Orders.Assign(value); }
    }
}

Возможна и обратная ситуация. Для описания ассоциации между клиентами и заказами вместо класса Customer можно использовать класс Order. Чтобы описать обратную связь с клиентом, класс Order использует тип EntityRef<TEntity>, как показано в следующем примере кода.

Bb386950.alert_note(ru-ru,VS.90).gifПримечание.

Класс EntityRef<TEntity> поддерживает отложенную загрузку. Дополнительные сведения см. в разделе Сравнение отложенной и немедленной загрузки (LINQ to SQL).

<Table(Name:="Orders")> _
Public Class Order
    <Column(IsPrimaryKey:=True)> _
    Public OrderID As Integer
    <Column()> _
    Public CustomerID As String
    Private _Customer As EntityRef(Of Customer)
    <Association(Storage:="Customer", ThisKey:="CustomerID")> _
    Public Property Customer() As Customer
        Get
            Return Me._Customer.Entity
        End Get
        Set(ByVal value As Customer)
            Me._Customer.Entity = value
        End Set
    End Property
End Class
[Table(Name = "Orders")]
public class Order
{
    [Column(IsPrimaryKey = true)]
    public int OrderID;
    [Column]
    public string CustomerID;
    private EntityRef<Customer> _Customer;
    [Association(Storage = "_Customer", ThisKey = "CustomerID")]
    public Customer Customer
    {
        get { return this._Customer.Entity; }
        set { this._Customer.Entity = value; }
    }
}

См. также

Основные понятия

Модель объектов LINQ to SQL

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

Как настроить классы сущностей с помощью редактора кода (LINQ to SQL)