数据库问题-外键始终为空(T-SQL)

时间:2019-02-12 13:55:40

标签: c# sql tsql ado.net

我描述的问题可能有点长,因为我们正在从事的项目规模更大,但是我将尽我所能来做到精确。

基本上,我们正在开发基于Web的伤口管理(大学项目的一部分),用户可以在其中输入伤口并设置其他信息,例如大小,稠度,上传图片,选择位置等。 所有这些信息都应存储在数据库(我们正在使用MS SQL Studio和Visual Studio 2017)中,用户以后也可以在数据库中检索它以在模块上查看它。

我们现在面临的问题是,如果要向用户显示特殊伤口,我们将无法使用外键。 我们可以通过案例编号(正在运行)进行过滤,但无法通过伤口的ID来过滤伤口信息(每个伤口都具有唯一的ID)-因此,如果选择伤口,我们仍会获得有关所有伤口的信息将存储给定的casenr。

这是我们的“主表”,每个伤口都获得一个唯一的ID,该ID也是一个递增的标识列:

    [wound_id]          INT           IDENTITY (1, 1) NOT NULL,
    [wound_type]        VARCHAR (500) NULL,
    [wound_description] VARCHAR (500) NULL,
    [decuGrade]         INT           NULL,
    [wound_comments]    VARCHAR (500) NULL,
    [wound_timeReal]    DATETIME      NULL,
    [wound_timeGiven]   DATETIME      NULL,
    [casenumber]        INT           NULL,
    [username]          VARCHAR (50)  NULL,
    PRIMARY KEY CLUSTERED ([wound_id] ASC)
);

如果用户输入信息并单击“下一步”,则会在代码后面调用一个函数,该函数将填充表格:

 _db.SaveWoundDetails(casenr, woundValue, decu, additional_info, realTime, givenBackDocDate, user);

这将导致我们的数据库类,在这种情况下,我们可以查询数据库:

 public void SaveWoundDetails(int casenr, string woundType, int decuGrade, string woundComment, DateTime timeReal, DateTime timeGiven , string user)
        {
            var table = ConfigurationManager.AppSettings["woundDetailsTable"];
            var insertQuery = "INSERT INTO " + table + "(casenumber, wound_type, decuGrade, wound_comments, wound_timeReal, wound_timeGiven, username) VALUES (@casenr, @woundType, @decuGrade, @woundComment, @timeReal, @timeGiven, @user)";


            var cmd = new SqlCommand(insertQuery);

            cmd.Parameters.AddWithValue("@casenr", casenr);
            cmd.Parameters.AddWithValue("@woundType", woundType);
            cmd.Parameters.AddWithValue("@decuGrade", decuGrade);
            cmd.Parameters.AddWithValue("@woundComment", woundComment);
            cmd.Parameters.AddWithValue("@timeReal", timeReal);
            cmd.Parameters.AddWithValue("@timeGiven", timeGiven);
            cmd.Parameters.AddWithValue("@user", user);
            var db = DatabaseController.getDataBaseController();

            try
            {
                var sqlcmd = db.executeSQL(cmd);
            }
            catch (SqlException e)
            {

            }
        }

连接等在当前不相关的数据库处理程序类中。

直到此处正常工作。但是,现在我们有了第二张表,以获取有关伤口的更多信息,该表也会在与该表相关的下一次单击时填充:

CREATE TABLE [dbo].[epadoc_mod_wound_progress] (
    [progress_id]       INT           IDENTITY (1, 1) NOT NULL,
    [wound_length]      INT           NULL,
    [wound_width]       INT           NULL,
    [wound_depth]       INT           NULL,
    [wound_surrounding] VARCHAR (500) NULL,
    [wound_consistence] VARCHAR (500) NULL,
    [wound_state]       VARCHAR (200) NULL,
    [wound_painscale]   VARCHAR (MAX) NULL,
    [wound_itch]        VARCHAR (MAX) NULL,
    PRIMARY KEY CLUSTERED ([progress_id] ASC)

使用INSERT-METHOD:

 public void SaveWoundProgress(int woundLength, int woundWidth, int woundDepth, string woundSurrounding, string woundConsistence, string woundState, string woundPainScale, string woundItch)
        {
            var table = ConfigurationManager.AppSettings["woundProgressTable"];
            var insertQuery = "INSERT INTO " + table + "(wound_length,wound_width,wound_depth, wound_surrounding, wound_consistence, wound_state, wound_painscale, wound_itch) VALUES (@woundLength, @woundWidth, @woundDepth, @woundSurrounding, @woundConsistence, @woundState, @woundPainScale, @woundItch)";


            var cmd = new SqlCommand(insertQuery);

            cmd.Parameters.AddWithValue("@woundLength", woundLength);
            cmd.Parameters.AddWithValue("@woundWidth", woundWidth);
            cmd.Parameters.AddWithValue("@woundDepth", woundDepth);
            cmd.Parameters.AddWithValue("@woundSurrounding", woundSurrounding);
            cmd.Parameters.AddWithValue("@woundConsistence", woundConsistence);
            cmd.Parameters.AddWithValue("@woundState", woundState);
            cmd.Parameters.AddWithValue("@woundPainScale", woundPainScale);
            cmd.Parameters.AddWithValue("@woundItch", woundItch);
            var db = DatabaseController.getDataBaseController();

            try
            {
                var sqlcmd = db.executeSQL(cmd);
            }
            catch (SqlException e)
            {

            }
        }

和方法

_db.SaveWoundProgress(wound_length, wound_width, wound_depth, woundArea, woundEdge, woundStatus, painStatus, itchStatus);

在上述方法之后立即执行。

我知道如何在两个表之间创建外键,但是我们尝试的所有操作都失败了-如果尝试使用不为NULL的外键集执行外键,则会得到空异常。

我们尝试过的例子:

CONSTRAINT [FK_epadoc_mod_wound_details] FOREIGN KEY ([wound_id])
REFERENCES [dbo].[epadoc_mod_wound_progress] ([progress_id])

如果我们这样设置一个外键,它将无法正常工作。

我们得出的结论是,当执行这两个方法时,调用栈一定是一个问题-但我们不知道如何解决。 也许我们必须在INSERT查询中将外键设置为显式变量?

我们要实现的是,将细节表的伤口ID作为进度表的外键,以便以后可以更改伤口(例如,如果伤口愈合,用户可以重新输入新的大小)等),我们可以按ID进行过滤,以仅向患者显示一个伤口,如果单击特定伤口,则不能同时显示所有伤口。

遗憾的是,我不是数据库专家,所以希望您能按照我的解释进行操作:)。

感谢您的帮助!

3 个答案:

答案 0 :(得分:3)

您的epadoc_mod_wound_progress需要包含一个[wound_id] INT NOT NULL列。这是您的外键应建立的基础,这样一个伤口可以有很多伤口进展。然后,在插入语句中,将在wound_id表插入中生成的woundDetail插入到epadoc_mod_wound_progress中。

答案 1 :(得分:1)

试图添加评论,但我没有50声望。

根据我的发现,我认为您正在尝试在“主表”和“ epadoc_mod_wound_progress”表之间实现一对多的关系,对吗?

如果是这样,您似乎在“ epadoc_mod_wound_progress”表中没有存储伤口ID的字段,如果不存储伤口ID,您如何尝试创建外键?

建议epadoc_mod_wound_progress表的主键是伤口ID和progress_id的串联键,而伤口ID也是链接到主表的外键。

答案 2 :(得分:1)

在表epadoc_mod_wound_progress中,必须有一个wound_id INT NOT NULL列用作外键。

还必须将约束添加到外键表,即 1到n 关系的 n 侧的表。假设主表的名称为epadoc_mod_wound_details(您没有显示它):

ALTER TABLE dbo.epadoc_mod_wound_progress
ADD CONSTRAINT FK_progress_details FOREIGN KEY (wound_id)
REFERENCES dbo.epadoc_mod_wound_details (wound_id)
ON DELETE CASCADE

此外,通过添加ON DELETE CASCADE,当您删除伤口细节时,伤口细节的进度也会自动删除。