0

I have 4 tables, IndividualTruck, TruckModel, TruckFeature and TruckFeatureAssociation.

IndividualTruck has a property TruckModel of Type TruckModel. After assigning other properties retrieved from a WPF form, I create the relationship and add these new records into the relevant tables shown below.

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 table class has int FeatureID, string Description and TruckFeatureAssociation : ICollection<TruckFeatureAssociation>

TruckFeatureAssociation table class has int TruckID, int FeatureID, Feature: TruckFeature and Truck: IndividualTruck.

I have a list box where multiple features can be selected out of the table TruckFeature, it's a table with four entries (Air conditioning, Rear door for loading, alarms system and keyless door).

I've attempted to loop through the list of selected features and retrieve the FeatureID of those selected to assign to assign the featureID to the association table which is two columns TruckID and FeatureID both primary keys.

When I go to save the data to the tables, I get a SQL error

SqlException: Cannot insert explicit value for identity column in table 'TruckFeature' when IDENTITY_INSERT is set to OFF.

Cannot insert explicit value as insert is OFF

How do I create this relationship without changing this insert OFF condition? TIA. Sorry for the messy question I'm REALLY new to .NET and C#.

UPDATE:

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

and

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

The error shows up next to ctx.savechanges();

BoogieMan
  • 71
  • 1
  • 1
  • 6
  • Please quote the exact error. It should also say which table is involved. Also, it would help to see the classes instead of descriptions, and the code of `AddNewTruck`, and to know the exact EF version and the database provider. In the end, all that happens here is that you try to add records that have a non-default key value into a table that has an identity column. – Gert Arnold Oct 30 '21 at 09:44
  • SqlException: Cannot insert explicit value for identity column in table 'TruckFeature' when IDENTITY_INSERT is set to OFF. EF v4.7.2 – BoogieMan Oct 30 '21 at 12:32
  • There is no EF 4.7.2. The .Net version is not the same a EF version. That said, so it must be *a* .Net-framework version of EF and that means that you simply didn't configure the column as identity column in EF's model. – Gert Arnold Oct 30 '21 at 19:57

1 Answers1

0

When working with references (navigation properties) you need to perform all fetches and saving with the same DbContext instance. This code here will be problematic:

public static TruckFeature SearchBySelected(string feature)
{
    using(DAD_BaldipContext ctx = new DAD_BaldipContext())
    { ... }
}

If each method instantiates a DbContext with a using() scope, the TruckFeature returned will not be "known" to the DbContext instance that you are using to save your association.

With MVC this can be managed fairly easily by using DI (Dependency Injection) to ensure that a single DbContext instance is associated to the Request, so all services etc. would have that single instance injected in their constructors.

With WPF it generally needs to be managed a little more manually. Often this means employing a Unit Of Work pattern that will manage the lifetime scope of a DbContext. However, for a start you can manage this by scoping a DbContext at the "top" level of your operation, and passing it to the various calls:

public static TruckFeature SearchBySelected(string feature, DAD_BaldipContext context)
{
    TruckFeature ff = context.TruckFeature.Where(f => f.Description == feature).FirstOrDefault();

    return ff;               
}

Realistically methods like this are probably not that practical, just fetch the data in-line via the DbContext within the single using scope.

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

This assumes that IndividualTruck.TruckFeatures is a many-to-many relationship between the truck and the feature. If TruckFeatures is using a shadow linking entity (IndividualTruck contains a collection of Features rather than TruckFeatures) then:

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)); 
}
Steve Py
  • 26,149
  • 3
  • 25
  • 43
  • I've editted my question to give a clearer picture is there anyway to make it work the way I have set it up using a DOA class etc. – BoogieMan Oct 30 '21 at 12:38
  • The SqlException: Cannot insert explicit value for identity column in table 'TruckFeature' when IDENTITY_INSERT is set to OFF. – BoogieMan Oct 30 '21 at 12:39
  • Yes, use the same, single instance of the DbContext for the whole operation rather than declaring one in each method. – Steve Py Oct 31 '21 at 00:08