方法 : データベース リレーションシップを割り当てる
データ リレーションシップが常に同じ場合は、これをエンティティ クラス内のプロパティ参照としてエンコードできます。 たとえば、Northwind サンプル データベースでは、通常は顧客が注文を発注するため、モデルには、顧客と注文のリレーションシップが常に存在します。
LINQ to SQL では、そのようなリレーションシップを表すのに役立つ AssociationAttribute 属性が定義されています。 この属性を、EntitySet<TEntity> 型および EntityRef<TEntity> 型と共に使用することで、データベース内の外部キー リレーションシップが表されます。 詳しくは、「属性ベースの対応付け」の関連付け属性のセクションをご覧ください。
Note
AssociationAttribute プロパティ値と ColumnAttribute Storage プロパティ値では大文字と小文字が区別されます。 たとえば、AssociationAttribute.Storage プロパティの属性に使用されている値は、コード内の別の場所で使用されている対応するプロパティ名と、大文字と小文字が一致するようにしてください。 これは、Visual Basic など、通常は大文字と小文字が区別されない言語を含むすべての .NET プログラミング言語に適用されます。 Storage プロパティの詳細については、「DataAttribute.Storage」を参照してください。
ほとんどのリレーションシップは、このトピックの例のように、一対多のリレーションシップです。 次に示すように、一対一および多対多のリレーションシップも表すことができます。
一対一: 両側で EntitySet<TEntity> を指定することによって、この種類のリレーションシップを表します。
たとえば、顧客のセキュリティ コードが
Customer
テーブルにはなく、承認されたユーザーのみがアクセスできるように作成された、Customer
-SecurityCode
リレーションシップがその例です。多対多: 多対多リレーションシップでは、リンク テーブル ("結合" テーブルともいいます) の主キーは、多くの場合、他の 2 つのテーブルの外部キーが結合して作成されます。
たとえば、リンク テーブル
Employee
を使用して作成される -Project
EmployeeProject
という多対多リレーションシップがあるとします。 LINQ to SQL では、このようなリレーションシップを、Employee
、Project
、EmployeeProject
という 3 つのクラスを使用してモデル化する必要があります。 この場合、Employee
とProject
の間のリレーションシップを変更すると、主キーのEmployeeProject
の更新が必要であるように見える可能性がありす。 ただし、この状態は、既存のEmployeeProject
の削除、および新しいEmployeeProject
の作成として適切にモデル化されます。Note
リレーショナル データベース内のリレーションシップは、通常、他のテーブルの主キーを参照する外部キー値としてモデル化されます。 それらの間を移動するには、リレーショナル "結合" 演算を使用して、2 つのテーブルを明示的に関連付けます。
これに対し、LINQ to SQL 内のオブジェクトは、"ドット" 表記を使用してナビゲートするプロパティ参照または参照のコレクションを使用して、互いを参照します。
例 1
次の一対多の例では、Customer
クラスは、顧客とその注文のリレーションシップを宣言するプロパティを持ちます。 Orders
プロパティは EntitySet<TEntity> 型です。 この型は、このリレーションシップが一対多 (1 人の顧客対多くの注文) であることを意味します。 OtherKey プロパティを使用して、この関連付けを実現する方法を記述します。つまり、これと比較する、関連クラス内のプロパティの名前を指定します。 この例では、データベース "結合" でその列の値が比較されるときに、CustomerID
プロパティが比較されます。
Note
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> 型を使用して、次のコード例に示すように、顧客へのリレーションシップを記述できます。
Note
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