Asignación de relaciones de base de datos

Puede codificar como referencias de propiedad en la clase de entidad cualquier relación de datos que vaya a ser siempre la misma. En la base de datos de ejemplo Northwind, por ejemplo, dado que los clientes normalmente realizan pedidos, hay siempre una relación en el modelo entre los clientes y sus pedidos.

LINQ to SQL define un atributo AssociationAttribute para ayudar a representar tales relaciones. Este atributo se utiliza junto con los tipos EntitySet<TEntity> y EntityRef<TEntity> para representar lo que sería una relación de clave externa en una base de datos. Para obtener más información, consulta la sección relativa al atributo de asociación de Mapeo Basado en Atributos.

Nota

Los valores de propiedad AssociationAttribute y ColumnAttribute Storage distinguen entre mayúsculas y minúsculas. Por ejemplo, asegúrese de que los valores utilizados en el atributo de la propiedad AssociationAttribute.Storage coinciden con el uso de mayúsculas y minúsculas para los nombres de propiedad correspondientes del resto del código. Esto se aplica a todos los lenguajes de programación de .NET, incluso a los que típicamente no distinguen entre mayúsculas y minúsculas, como Visual Basic. Para obtener más información acerca de la propiedad Storage, vea DataAttribute.Storage.

La mayoría de las relaciones son de uno a varios, como en el ejemplo que se incluye más adelante en este tema. También puede representar relaciones uno a uno y varios a varios de la manera siguiente:

  • Uno a uno: para representar este tipo de relación incluya EntitySet<TEntity> en ambos lados.

    Por ejemplo, considere una relación Customer-SecurityCode, creada de forma que el código de seguridad del cliente no se encuentre en la tabla Customer y solo esté accesible para las personas autorizadas.

  • Varios a varios: en las relaciones varios a varios, la clave principal de la tabla de vínculos (también conocida como tabla de unión) suele estar formada por un conjunto de claves externas de las otras dos tablas.

    Por ejemplo, considere una relación varios a varios Employee-Project formada mediante la tabla de vínculos EmployeeProject. LINQ to SQL requiere que tal relación se modele utilizando tres clases: Employee, Project, y EmployeeProject. En este caso, al cambiar la relación entre Employee y Project puede parecer necesario actualizar la clave principal de EmployeeProject. Sin embargo, esta situación se modela mejor eliminando un EmployeeProject existente y creando un nuevo EmployeeProject.

    Nota

    Las relaciones en las bases de datos relacionales se modelan normalmente como valores de clave externa que hacen referencia a claves principales de otras tablas. Para navegar entre ellas, las dos tablas se asocian explícitamente, utilizando una operación de combinación relacional.

    Por otra parte, las referencias mutuas entre los objetos de LINQ to SQL se realizan mediante referencias de propiedad o colecciones de referencias por las que se navega mediante la notación de punto.

Ejemplo 1

En el siguiente ejemplo de relación uno a varios, la clase Customer tiene una propiedad que declara la relación entre los clientes y sus pedidos. La propiedad Orders es de tipo EntitySet<TEntity>. Este tipo indica que esta relación es de uno a varios (entre un cliente y varios pedidos). La propiedad OtherKey se utiliza para describir cómo se logra esta asociación, a saber, especificando el nombre de la propiedad de la clase relacionada que se va a comparar con ésta. En este ejemplo, se compara la propiedad CustomerID, de igual forma que una combinación de base de datos compararía ese valor de columna.

Nota

Si utiliza Visual Studio, puede utilizar Object Relational Designer para crear una asociación entre clases.

[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

Ejemplo 2

También puede invertir la situación. En lugar de utilizar la clase Customer para describir la asociación entre los clientes y los pedidos, puede utilizar la clase Order. La clase Order utiliza el tipo EntityRef<TEntity> para describir paso a paso la relación hasta el cliente, como se observa en el ejemplo de código siguiente.

Nota

La clase EntityRef<TEntity> admite la carga aplazada. Para obtener más información, consulta Carga diferida frente a inmediata.

[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

Consulte también