我试图弄清楚是否可以使用 LINQ to SQL 执行“插入...选择”类型的命令。一些 LINQ to SQL 代码可以让我向数据库发送一个 SQL 命令,该命令会将多行插入给定的表中。
例如,如何使 LINQ to SQL 将以下 T-SQL 语句发送到 SQL Server 数据库?
INSERT INTO Table1
SELECT Table2.column1 + 1 AS column1, Table2.column2 + 2 AS column2
WHERE Table2.column3 > 100
我当然可以通过使用该DataContext.ExecuteCommand
功能来实现这一点,但这将立即执行,而无需利用您获得的自动事务处理DataContext.SubmitChanges
。除了这个之外,我还有一系列更新,我希望它们全部回滚以防出错。
有任何想法吗?
更新:这是实际代码:
var bs_prep =
from b in dc.T_EDR_FILEBODies
join
unpaid in dc.V_UNPAIDs
on
b.NUM_ADC.Substring(1, 9) equals unpaid.NOCONT
join
acordo in dc.T_ACORDOS_RECOM_APREs
on
Convert.ToInt32(b.NUM_ADC.Substring(1, 9)) equals acordo.ID_Contrato
where
b.ID_EDR == id_edr
&&
(
unpaid.NUM_INCUMPRIMENTOS <= max_unpaid_consec
&&
unpaid.TOTAL_NUM_INCUPRIMENTOS <= max_unpaid_nonconsec
)
||
(
acordo.Activo == true
&&
acordo.Data_Recomeco <= now
)
select new
{
ID_EDR = id_edr_filt,
NUM_LINHA = b.NUM_LINHA,
CODREJ = b.CODREJ,
HDT = b.HDT,
IMPORT = b.IMPORT,
NIB_DEV = b.NIB_DEV,
NUM_ADC = b.NUM_ADC,
REF_DD_BC = b.REF_DD_BC,
REF_MOV = b.REF_MOV
}
;
dc.T_EDR_FILEBODies.InsertAllOnSubmit(
bs_prep.Select(
b => new T_EDR_FILEBODY{
CODREJ = b.CODREJ,
HDT = b.HDT,
ID_EDR = b.ID_EDR,
IMPORT = b.IMPORT,
NIB_DEV = b.NIB_DEV,
NUM_ADC = b.NUM_ADC,
NUM_LINHA = b.NUM_LINHA,
REF_DD_BC = b.REF_DD_BC,
REF_MOV = b.REF_MOV
}
)
);
快速解释:T_EDR_FILEBODies
实体映射到一个数据库表,该表基本上存储了我们导入的一些文本文件的内容。一条记录对应文本文件中的一行。
我要做的是通过从一个文件中复制记录来创建文件内容的过滤版本,给它们一个新的文件 ID ( ID_EDR=id_edr_filt
),但过滤掉一些行。LINQ to SQL 实体是到数据库表的直接映射。到目前为止,我没有向我的数据上下文添加任何代码。它们确实有主键,否则我将无法对它们进行插入(我在某处读过,如果我摆脱了主键,我将能够摆脱该异常,但是如您所见,那不会在我的情况下工作)。
当我运行它时,我得到以下异常抛出InsertAllOnSubmit
:
不允许在查询中显式构造实体类型“T_EDR_FILEBODY”。
我想我明白在查询中显式构造实体会出现问题。查询返回的实体具有更改跟踪,调用 submitchanges 时会将更改转换到数据库中。但是,您如何将在客户端创建的实体上的更改转换到数据库中呢?但这真的意味着您永远无法使用 LINQ to SQL 执行 INSERT INTO...SELECT 类型的命令吗?