SQL Server, LINQ-to-SQL and representing multiple components in a container class
This question is in two parts:
A) Is my design wrong? If so, what would be the proper way to do this?
B) If my design is right, how do I implement it?
I have a data class that consists of multiple instances of a component class. An abstraction of the class structure would be this:
In this example I have only two components in the container but in reality I have more. It's also important to point out that Container
cares about which Component
is which - they can't just be a list, they have individual names and meaning to the Container
.
I've implemented the following structure in MS SQL Server 2008 to store this data:
CREATE TABLE Containers (
ID int IDENTITY(1,1) NOT NULL,
ComponentA int NULL,
ComponentB int NULL,
CONSTRAINT PK_Containers PRIMARY KEY (ID));
CREATE TABLE Components (
ID int IDENTITY(1,1) NOT NULL,
Foo nchar(10) NOT NULL,
Bar nchar(10) NOT NULL,
CONSTRAINT PK_Components PRIMARY KEY (ID));
ALTER TABLE Containers
ADD CONSTRAINT FK_ComponentA
FOREIGN KEY (ComponentA)
REFERENCES Components(ID);
ALTER TABLE Containers
ADD CONSTRAINT FK_ComponentB
FOREIGN KEY (ComponentB)
REFERENCES Components(ID);
This already has a few drawbacks:
In my model, components are unique, and can only belong to one property on one Container. In the DB, I have to enforce this manually.
When a Con开发者_运维知识库tainer is deleted, the Components it references should also be deleted. This I have to do manually in the DB (with a trigger).
The big problem, however, is this:
I use LINQ-TO-SQL for my database access in the C# WPF MVVM desktop application I am building in Visual Studio 2010. When I pull the database tables above into the LINQ-TO-SQL designer, this is what I get:
I can manually set the relationships to One-to-One in the LING-TO-SQL designer, to stop the Component
instances from having sets of type Container
.
Correctly, each Container
has two Component
references. However, the Component
instances still have two Container
references, where my model requires them to have only one.
How can I implement my class design in SQL Server or how can I convince LINQ-to-SQL to interpret my database the way I intended?
A container has many components, but needs to reference them by name. You need a relationship table from container to component (in pseudo-sql):
create table ContainerComponents (
ContainerID int FK references Container(ID),
ComponentID int FK references Component(ID),
Name string,
-- optional - to give the relationship a meaning
Type int FK references RelationshipType(ID)
)
To answer this question:
In my model, components are unique, and can only belong to one property on one Container. In the DB, I have to enforce this manually.
Just create a unique constraint in ContainerComponents
for ContainerID
and ComponentID
.
And this one:
When a Container is deleted, the Components it references should also be deleted. This I have to do manually in the DB (with a trigger).
Use cascade deletes from Container
to ContainerComponents
to Component
.
精彩评论