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


Практическое руководство. Сопоставление связей базы данных

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

LINQ to SQL определяет AssociationAttribute атрибут для представления таких связей. Этот атрибут используется совместно с типами EntitySet<TEntity> и EntityRef<TEntity> для представления в базе данных связи по внешнему ключу. Дополнительные сведения см. в разделе "Атрибут ассоциации" сопоставления на основе атрибутов.

Примечание.

В значениях свойства 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.

    Примечание.

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

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

Пример 1

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

Примечание.

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

[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); }
    }
}
<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

Пример 2

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

Примечание.

Класс EntityRef<TEntity> поддерживает отложенную загрузку. Дополнительные сведения см. в разделе "Отложенная и немедленная загрузка".

[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; }
    }
}
<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

См. также