如何在主键插入关闭的两个对象之间创建关系?

Posted

技术标签:

【中文标题】如何在主键插入关闭的两个对象之间创建关系?【英文标题】:How to create relationship between two objects where primary key insert is OFF? 【发布时间】:2021-12-15 01:40:02 【问题描述】:

我有 4 个表,IndividualTruck、TruckModel、TruckFeature 和 TruckFeatureAssociation。

IndividualTruck 具有 TruckModel 类型的属性 TruckModel。在分配从 WPF 表单检索的其他属性后,我创建关系并将这些新记录添加到如下所示的相关表中。

IndividualTruck truck = new IndividualTruck();
truck.Colour = Colour; #various other attributes

TruckModel model =  new TruckModel();
model.Manufacturer = new Manufacturer; #various other attributes

truck.TruckModel = model; #creating the relationship

#this function checks adds the new truck and saves the table
DAO.AddNewTruck(truck, true); 

TruckFeature 表类有int FeatureIDstring DescriptionTruckFeatureAssociation : ICollection<TruckFeatureAssociation>

TruckFeatureAssociation 表类有int TruckIDint FeatureIDFeature: TruckFeatureTruck: IndividualTruck

我有一个列表框,可以从表格TruckFeature 中选择多个功能,它是一个有四个条目的表格(空调、装载后门、警报系统和无钥匙门)。

我尝试遍历所选功能列表并检索选择分配的FeatureID 以将featureID 分配给关联表,该关联表是两列TruckIDFeatureID 都是主键.

当我将数据保存到表中时,出现 SQL 错误

SqlException:当 IDENTITY_INSERT 设置为 OFF 时,无法在表“TruckFeature”中插入标识列的显式值。

无法插入显式值,因为插入已关闭

如何在不更改此插入关闭条件的情况下创建此关系? TIA。抱歉,我对 .NET 和 C# 很陌生。

更新:

for (int i = featureListBox.SelectedItems.Count - 1; i >= 0; --i)
            
                TruckFeatureAssociation association = new TruckFeatureAssociation();
                TruckFeature truckFeature = new TruckFeature();
                
                string feature = featureListBox.SelectedItems[i].ToString();

                truckFeature = DAO.SearchBySelected(feature);

                association.Feature = truckFeature;
                association.Truck = truck;

                DAO.addNewFeatureAssc(association);
            

public static void addNewFeatureAssc(TruckFeatureAssociation ff)
        
            using (DAD_BaldipContext ctx = new DAD_BaldipContext())
            
                ctx.TruckFeatureAssociation.Add(ff);
                ctx.SaveChanges();
                
        

错误显示在 ctx.savechanges() 旁边;

【问题讨论】:

请引用确切的错误。它还应该说明涉及哪个表。此外,查看类而不是描述以及AddNewTruck 的代码以及了解确切的 EF 版本和数据库提供程序将有所帮助。最后,这里发生的只是您尝试将具有非默认键值的记录添加到具有标识列的表中。 SqlException:当 IDENTITY_INSERT 设置为 OFF 时,无法在表“TruckFeature”中插入标识列的显式值。 EF v4.7.2 没有 EF 4.7.2。 .Net 版本与 EF 版本不同。也就是说,它必须是 EF 的 a .Net 框架版本,这意味着您根本没有将列配置为 EF 模型中的标识列。 【参考方案1】:

使用引用(导航属性)时,您需要使用相同的 DbContext 实例执行所有提取和保存。这里的代码会有问题:

public static TruckFeature SearchBySelected(string feature)

    using(DAD_BaldipContext ctx = new DAD_BaldipContext())
     ... 

如果每个方法都实例化具有using() 范围的 DbContext,则返回的 TruckFeature 将不会被您用来保存关联的 DbContext 实例“知道”。

使用 MVC,这可以通过使用 DI(依赖注入)相当容易地进行管理,以确保单个 DbContext 实例与请求相关联,因此所有服务等都将在其构造函数中注入该单个实例。

使用 WPF,它通常需要更多手动管理。这通常意味着使用一个工作单元模式来管理 DbContext 的生命周期范围。但是,首先,您可以通过在操作的“***”级别限定 DbContext 并将其传递给各种调用来管理它:

public static TruckFeature SearchBySelected(string feature, DAD_BaldipContext context)

    TruckFeature ff = context.TruckFeature.Where(f => f.Description == feature).FirstOrDefault();

    return ff;               

实际上,这样的方法可能不太实用,只需通过单个 using 范围内的 DbContext 在线获取数据。

using (var context = new DAD_BaldipContext())

    IndividualTruck truck = new IndividualTruck
    
        truck.Colour = Colour; #various other attributes
        TruckModel = new TruckModel 
        
            Manufacturer = new Manufacturer  ... 
         // Assuming you need to create a new model, otherwise...
        // TruckModel = context.TruckModels.Single(x => /* Query to find the correct model selected. */);
    ;

    for (int i = featureListBox.SelectedItems.Count - 1; i >= 0; --i)
    
        string feature = featureListBox.SelectedItems[i].ToString();
        TruckFeatureAssociation association = new TruckFeatureAssociation
        
            Feature = context.Features.Single(x => x.Description == feature);
        
        truck.TruckFeatures.Add(association); 
    
    context.SaveChanges();

这假设 IndividualTruck.TruckFeatures 是卡车和特征之间的多对多关系。如果 TruckFeatures 使用影子链接实体(IndividualTruck 包含一组功能而不是 TruckFeatures),则:

for (int i = featureListBox.SelectedItems.Count - 1; i >= 0; --i)

    string feature = featureListBox.SelectedItems[i].ToString();
    truck.Features.Add(context.Features.Single(x => x.Description == feature)); 

【讨论】:

我已经编辑了我的问题,以提供更清晰的画面,无论如何,它是否可以按照我使用 DOA 类等设置的方式工作。 SqlException:当 IDENTITY_INSERT 设置为 OFF 时,无法在表“TruckFeature”中插入标识列的显式值。 是的,对整个操作使用相同的单个 DbContext 实例,而不是在每个方法中声明一个。

以上是关于如何在主键插入关闭的两个对象之间创建关系?的主要内容,如果未能解决你的问题,请参考以下文章

数据库外键约束?

ACCESS中如何让表关联

SQL数据库里面怎样设置表与表之间的关联

当主键列不是标识列时如何插入数据?

在cowplot中使用axis_canvas的边际图:如何在主面板和边际图之间插入间隙

如何设置SQL数据库表与表的关联关系?