Как сопоставить связи базы данных (LINQ to SQL)
Обновлен: November 2007
Отношения данных, которые всегда останутся неизменными, можно закодировать в виде ссылок в классе сущностей. В учебной базе данных Northwind, всегда существует связь между заказчиками и их заказами, т.к. обычно заказчики размещают заказы.
LINQ to SQL определяет атрибут AssociationAttribute, с помощью которого представляются такие отношения. Этот атрибут используется вместе с типами EntitySet<TEntity> и EntityRef<TEntity> для представления в базе данных отношения внешнего ключа. Дополнительные сведения см. в подразделе «Атрибут Association» раздела Сопоставление на основе атрибутов (LINQ to SQL).
Примечание. |
---|
В значениях свойства 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 ссылаются друг на друга с помощью ссылок свойств или коллекций ссылок, к которым можно перейти с использованием точечной нотации.
Пример
В следующем примере отношения "один-ко-многим" класс Customer имеет свойство, объявляющее отношение между клиентами и их заказами. Свойство Orders имеет тип EntitySet<TEntity>. Этот тип указывает, что данное отношение относится к виду "один-ко-многим" (один клиент — много заказов). Свойство OtherKey используется для описания установки данной связи, а именно: путем указания в связанном классе имени свойства, которое будет сравниваться с существующим. В этом примере свойство CustomerID сравнивается таким образом, как если бы соединение базы данных сравнивалось с данным значением столбца.
Примечание. |
---|
Если разработка ведется в среде 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>, как показано в следующем примере кода.
Примечание. |
---|
Класс 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)