首页 > 解决方案 > 如何在主键插入关闭的两个对象之间创建关系?

问题描述

我有 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 FeatureID,string DescriptionTruckFeatureAssociation : ICollection<TruckFeatureAssociation>

TruckFeatureAssociation表类有int TruckIDint FeatureID和。Feature: 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() 旁边;

标签: c#.netwpfentity-frameworkdao

解决方案


使用引用(导航属性)时,您需要使用相同的 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;               
}

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

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)); 
}

推荐阅读