使用主键同时存储到两个表中

时间:2013-10-21 15:55:39

标签: sql-server database vb.net linq-to-sql

我需要同时将校准存储到两个表中,一个表描述校准的实例(操作员,日期,站),另一个表将原始数据存储在多行中(9或10对波长和响应度)单次校准)。其架构如下:

Spectrometer calibration schema

示例校准:

Spectrometer calibration data

所有校准点的SpectrometerCalibration.ID = SpectrometerCalibrationID。我尝试过(在vb.net中使用LINQ to SQL,因此将其视为伪代码)

INSERT INTO SpectrometerCalibration (StationID, OperatorID, Date) VALUES (7, 2, '2013/10/21 11:00:00.000 AM')

SELECT TOP 1 ID FROM SpectrometerCalibration ORDER BY ID DESC

-- Insert once for each wavelength / responsivity pair
INSERT INTO SpectrometerCalibrationValues (SpectrometerCalibrationID, Wavelength, Responsivity) VALUES (<from previous query>, <wl>, <val>)

此解决方案存在时序问题。如果两个站同时校准,则可以返回错误的ID。我相信这是糟糕的设计。试图避免这种方法。

我在SO上看到了更复杂的问题,但似乎没有一个能解决我的问题。我假设有一种标准的方法来正确地做到这一点。不,我无法更改此架构。我在vb.net中使用LINQ to SQL。这是一个更好的方法吗?

3 个答案:

答案 0 :(得分:2)

在SQL Server中,它看起来像这样:

DECLARE @NewID int

INSERT INTO SpectrometerCalibration (StationID, OperatorID, Date)
VALUES (7, 2, '2013/10/21 11:00:00.000 AM')

SELECT @NewID = SCOPE_IDENTITY()

-- Insert once for each wavelength / responsivity pair
INSERT INTO SpectrometerCalibrationValues (SpectrometerCalibrationID, Wavelength, Responsivity)
VALUES (@NewID , <wl>, <val>)

要在LINQ2SQL中实现相同的结果,您可以使用:

using (var dbc = new yourDataContext())
{
    var calibration = new SpectrometerCalibration
        {
            StationID = 7,
            OperatorID = 2,
            Date = dateTime.Now
        };
    dbc.calibrations.InsertOnSubmit(calibration );
    dbc.SubmitChanges();

    var clibrationValue = new SpectrometerCalibrationValue
          {
              SpectrometerCalibrationID = calibration.Id,
              Wavelength = 1,
              Responsivity = 1
          };
    dbc.clibrationValues.InsertOnSubmit(clibrationValue);
    dbc.SubmitChanges();
}

答案 1 :(得分:0)

Linq-to-Sql(你提到过你正在使用的)是最好的方法之一。

您只需要创建对象:

SpectrometerCalibration calibration = new SpectrometerCalibration();
yourDataContext.SpectrometerCalibrations.InsertOnSubmit(calibration);
yourDataContext.SubmitChanges();
// After the line above Linq-to-Sql retrieves the id of the calibration object.

// Then, you could make your values:
SpectrometerCalibrationValue value = new SpectrometerCalibrationValue();
value.SpectrometerCalibrationID = calibration.Id;
// Don't forget to update the calibration data in the value objects.
yourDataContext.SpectrometerCalibrationValues.InsertOnSubmit(value);
yourDataContext.SpectrometerCalibrationValues.InsertOnSubmit(value2);
// Etc ...

yourDataContext.SubmitChanges();

但是,我强烈建议您更改架构以将外键放在另一个表上。

答案 2 :(得分:0)

在这种情况下,我倾向于使用存储过程,因此数据库层中的控制权实际上发生了什么,并且它允许在返回信息之前对信息执行更复杂的逻辑。应用层。

在这种情况下,假设Date不是表上自然键的一部分,T-SQL逻辑将被塑造成看起来像这样。

INSERT INTO SpectrometerCalibration (StationID, OperatorID, Date)
SELECT 
FROM (SELECT @StationID [StationID], @OperatorID [OperatorID], @Date [DateStamp]) T
LEFT JOIN SpectrometerCalibration C ON
    C.StationID = T.StationID
    AND C.OperatorID = T.OperatorID
WHERE C.ID IS NULL

SELECT @SpectrometerCalibrationID = ID
FROM SpectrometerCalibration 
WHERE StationID = @StationID
    AND OperatorID = @OperatorID
    --Not known if Date is part of combination which uniquely identifies a row
    --AND Date = @Date

INSERT INTO SpectrometerCalibrationValues (SpectrometerCalibrationID, Wavelength, Responsivity)
VALUES (@SpectrometerCalibrationID, <S