我的数据库中有以下表结构:
create table Encargado(
ID int primary key,
Nombre varchar(300),
)
create table Area(
ID int primary key,
Nombre varchar(300),
Jefe int foreign key references Encargado(ID)
)
create table Carrera(
ID int primary key,
Nombre varchar(300),
Area int foreign key references Area(ID)
)
create table Formacion(
ID int primary key,
Grado varchar(300),
Lugar varchar(300)
)
create table Docente(
ID int primary key,
Nombre varchar(300),
Carrera int foreign key references Carrera(ID),
Formacion int foreign key references Formacion(ID),
Horario varchar(300)
)
create table Evaluacion(
ID int primary key,
Docente int foreign key references Docente(ID),
Evaluador varchar(300),
Secuencia int,
Pizarra int,
Audiovisual int,
Letra int,
Voz int,
GestosVocabulario int,
Ejemplificacion int,
Respuestas int,
DominioEscenico int,
Participacion int,
Observacion varchar(4000),
Materias varchar(3000),
Valido bit
)
create table Seguimiento(
ID int primary key,
Docente int foreign key references Docente(ID),
Modulo int,
Semestre int,
Ano int,
Fecha datetime,
Hora datetime,
OrdenSecuencia bit,
OrdenSecuenciaObservacion varchar(200),
PortafolioAlumno bit,
PortalofioAlumnoObservacion varchar(200),
AspectosParaEntrevista varchar(3000),
Conclusiones varchar(3000),
Evaluador varchar(300),
DirectorDeArea int foreign key references Encargado(ID),
EncargadoControl int foreign key references Encargado(ID),
)
说我要删除一个区域,我该怎么做?我还需要删除所有Carreras以及所有Docentes。
public void Delete(Area area)
{
db.Carreras.DeleteAllOnSubmit(area.Carreras);
//I'm stuck here. Is this what I should be doing?
}
有人可以建议如何处理吗?
我正在使用C#和Linq-to-SQL。我觉得我可能通过使用这个表结构或者这可能是关系数据库的一个缺点而陷入困境? :\
答案 0 :(得分:2)
我不会在Linq-to-SQL方面处理这个问题,如果你真的想要删除所有子记录,我会在数据库端使用级联删除。
例如,使用Oracle,您可以在create table语句中添加“ON DELETE CASCADE”子句,请参阅this链接。
级联删除将处理从子表中删除所有记录,所有记录都只需一次删除操作。这种方法的优点在于,无论您在哪里执行操作,尽管通过Linq-To-SQL,JAVA,ROR,PHP等,逻辑都集中在数据库中,因此无论谁执行删除,它的工作方式都相同
答案 1 :(得分:1)
它应该取决于您希望如何处理外键关系。即删除外国参考文献或留下参考文献,以防其他条目依赖于他们,等等
请参阅参照完整性http://msdn.microsoft.com/en-us/library/ms186973.aspx
所以,最后你应该让DB处理它。
答案 2 :(得分:0)
说我要删除一个区域,怎么做 我会这样做吗?我还需要 删除所有Carreras以及所有 Docentes。
从表面上看,您似乎希望将ON DELETE
的声明性参照完整性(DRI)操作从默认的NO ACTION
更改为(即阻止引用的行被删除)到{{ 1}}(即也删除参考表中的行)。
请注意,此类逻辑通常建议将引用列(例如CASCADE
)定义为Carrera.Area
。
例如:
NOT NULL
然而,看得更深,我们看到了
CREATE TABLE Carrera
(
...
Area INTEGER NOT NULL
REFERENCES Area (ID)
ON DELETE CASCADE
);
CREATE TABLE Docente
(
...
Carrera INTEGER NOT NULL
REFERENCES Carrera (ID)
ON DELETE CASCADE,
...
);
您需要考虑这些是否也需要Evaluacion REFERENCES Docente
Seguimiento REFERENCES Docente
DRI操作。
此外:
ON DELETE CASCADE
换句话说,你有一个潜在的循环。即使您的DBMS允许Seguimiento REFERENCES Encargado -- twice
Area REFERENCES Encargado
DRI对所有这些操作(例如,SQL Server),您应该考虑通过“手动”删除行来管理逻辑。
要考虑的其他事项,看到所有看似可以为NULL的列(但主键列如何可以为空??),您可以考虑ON DELETE CASCADE
DRI操作。就个人而言,我会通过删除NULLable列来创建新的关系表来澄清设计,但这可能涉及很多工作:)
答案 3 :(得分:0)
您是否考虑过“逻辑删除”而不是物理删除?
当您希望保持对数据(对于报表或查询)的历史访问时,即使它们已经过时,逻辑删除也是有意义的。
示例:您的学校曾经教过拉丁语,并且有一些教授教授它,还有一些学生注册。 明年,拉丁语将从可用课程中删除。其中一位教授退休,其他人继续其他课程。学生仍然需要证明他们在拉丁语中获得投票,即使这不会成为未来产品的一部分。
解决方案:在课程表中添加一个布尔标志(Active = Y / N)并调整您的程序,使其排除必须返回的查询中具有“Active = N”的课程(或教授或其他任何内容) “活着”,并让他们参与历史报道。