违反PRIMARY KEY约束,即使我没有在上下文中添加或修改任何内容

时间:2018-04-06 06:23:04

标签: c# entity-framework

我的程序正在解析xml文件并将此文件中的订单添加到mssql数据库。在将这些订单添加到数据库之前,如果有任何需要处理的重复项,他会对它们进行分析。

        foreach (var newOrderXml in newOrdersList)
        {                          
            var dupesInDb = _context.OrdersXml.Include(o=>o.OrderXmlItems)
                                              .Where(o => o.OrX_ORDERNR.Contains(newOrderXml.OrX_ORDERNR))
                                              .ToList();
            _context.SaveChanges();
        }

程序循环遍历newOrderList中的所有新订单,并使用linq查询获取重复列表。如果有0个重复项并且没有返回任何内容,则一切正常,但如果返回单个副本,则SaveChanges方法将抛出异常"违反PRIMARY KEY约束PK_dbo.SewingCardBundles,无法在对象中插入重复键&#39 ; dbo.SewingCardBundles&#39 ;.重复的键值是(1)。",即使我没有在上下文中添加或修改任何内容。我真的不知道发生了什么,我正在做的就是得到,我不改变任何东西,我不创造新的对象。这个异常恰好发生在这个位置,如果我尝试在此linq查询之前保存更改,那么没有什么不好的事情发生,但如果我在这个linq查询后尝试它我得到例外。那么这些对环境的变化来自哪里呢?

以下是我的模特:

public class OrderXml 
    {
        public OrderXml()
        {
            OrderXmlItems = new List<OrderXmlItem>();
        }

        public int OrX_Id { get; set; }
        public string OrX_ORDERNR { get; set; }
        public string OrX_REFERGB { get; set; }
        public int? OrX_CUSTOMERNUM { get; set; }
        public string OrX_DNAME { get; set; }
        public string OrX_DADR { get; set; }
        public string OrX_DPCODE { get; set; }
        public string OrX_POSTALCODE { get; set; }
        public string OrX_COUNTRY { get; set; }
        public string OrX_PHONE { get; set; }
        public string OrX_EMAIL { get; set; }
        public int? OrX_LANG { get; set; }
        public int? OrX_CUSTGRP { get; set; }
        public int? OrX_QUALITCON { get; set; }
        public string OrX_SHIPVIA { get; set; }
        public string OrX_DATE1 { get; set; }
        public string OrX_DATE2 { get; set; }
        public string OrX_DELIVGB { get; set; }
        public string OrX_SORT { get; set; }
        public int? OrX_CURLAB { get; set; }

        public List<OrderXmlItem> OrderXmlItems { get; set; }

        public Adress Adress { get; set; }
}


public OrderXmlItem()
        {
            SewingCardBundle = new SewingCardBundle();

        }

        public int OxI_Id { get; set; }
        public int? OxI_PRODUCT { get; set; }
        public int? OxI_ORDERLINE { get; set; }
        public int? OxI_QUANTITY { get; set; }
        public int? OxI_TYPE { get; set; }
        public string OxI_TPFABNR { get; set; }
        public string OxI_TPFABDEF { get; set; }
        public string OxI_TPFABNAME { get; set; }
        public int? OxI_CURDIR { get; set; }
        public int? OxI_CURWIDTH { get; set; }
        public int? OxI_CURHEIGHT { get; set; }
        public int? OxI_WORKMETH { get; set; }
        public int? OxI_FOLDTYPE { get; set; }
        public decimal? OxI_FOLDFACT { get; set; }
        public int? OxI_CURBAND { get; set; }
        public int? OxI_CURHEAD { get; set; }
        public int? OxI_CURBOTSEAM { get; set; }
        public int? OxI_PACKWLEFT { get; set; }
        public int? OxI_PACKWRIGHT { get; set; }
        public decimal? OxI_NRSTROL { get; set; }
        public decimal? OxI_NRSTROR { get; set; }
        public int? OxI_LINTYP { get; set; }
        public string OxI_LINCOL { get; set; }
        public int? OxI_EMBSORT { get; set; }
        public int? OxI_EXTRA { get; set; }
        public int? OxI_PRODUCE { get; set; }
        public int? OxI_PACKSORT { get; set; }
        public int? OxI_CURMODEL { get; set; }
        public string OxI_BARCODE { get; set; }
        public string OxI_EXTRAINF { get; set; }
        public int? OxI_RAILTYP { get; set; }
        public int? OxI_RAILCONT { get; set; }
        public int? OxI_RAILCONTSIDE { get; set; }
        public decimal? OxI_FABSTROTOT { get; set; }
        public decimal? OxI_FABSTROLEFT { get; set; }
        public decimal? OxI_FABSTRORIGHT { get; set; }
        public int? OxI_FABUNDSIZ { get; set; }
        public int? OxI_FABTOTSIZ { get; set; }
        public int? OxI_LINSTROTOT { get; set; }
        public int? OxI_LINUNDSIZ { get; set; }
        public int? OxI_LINTOTSIZ { get; set; }
        public decimal? OxI_FABWIDTH { get; set; }
        public int? OxI_CHILDSFT { get; set; }
        public int? OxI_FOLDSORT { get; set; }
        public int? OxI_EMBLENGTH { get; set; }
        public int? OxI_PACKMETH { get; set; }


        public int OrderXmlId { get; set; }
        public OrderXml OrderXml { get; set; }


        public SewingCardBundle SewingCardBundle { get; set; }
    }


public class SewingCardBundle
    {
        public SewingCardBundle()
        {
            FlamanSewingCards = new List<FlamandzkaSewingCard>();
            FlamandzkaBrytaSewingCards = new List<FlamandzkaBrytaSewingCard>();
            OczkaSewingCards = new List<OczkaSewingCard>();
            OczkaBrytaSewingCards = new List<OczkaBrytaSewingCard>();
            WellenbandSewingCards = new List<WellenbandSewingCard>();
            WellenbandBrytaSewingCards = new List<WellenbandBrytaSewingCard>();
            PodwiazkaSewingCards = new List<PodwiazkaSewingCard>();
            TunelSewingCards = new List<TunelSewingCard>();
        }

        public int SwC_Id { get; set; }

        public OrderXmlItem OrderXmlItem { get; set; }

        public List<FlamandzkaSewingCard> FlamanSewingCards { get; set; }
        public List<FlamandzkaBrytaSewingCard> FlamandzkaBrytaSewingCards { get; set; }
        public List<OczkaSewingCard> OczkaSewingCards { get; set; }
        public List<OczkaBrytaSewingCard> OczkaBrytaSewingCards { get; set; }
        public List<WellenbandSewingCard> WellenbandSewingCards { get; set; }
        public List<WellenbandBrytaSewingCard> WellenbandBrytaSewingCards { get; set; }
        public List<PodwiazkaSewingCard> PodwiazkaSewingCards { get; set; }
        public List<TunelSewingCard> TunelSewingCards { get; set; }
    }

以及这些模型的Fluent API配置:

     public class OrderXmlConfiguration : EntityTypeConfiguration<OrderXml>
            {
                public OrderXmlConfiguration()
                {
                    HasKey(o => o.OrX_Id);

                    Property(o => o.OrX_ORDERNR).IsRequired();
                    Property(o => o.OrX_REFERGB).IsRequired();
                    Property(o => o.OrX_CUSTOMERNUM).IsRequired();
                    Property(o => o.OrX_DNAME).IsRequired();
                    Property(o => o.OrX_DPCODE).IsRequired();
                    Property(o => o.OrX_POSTALCODE).IsRequired();
                    Property(o => o.OrX_COUNTRY).IsRequired();
                    Property(o => o.OrX_LANG).IsRequired();
                    Property(o => o.OrX_CUSTGRP).IsRequired();
                    Property(o => o.OrX_SHIPVIA).IsRequired();
                    Property(o => o.OrX_CURLAB).IsRequired();

                    HasMany(i => i.OrderXmlItems)
                        .WithRequired(o => o.OrderXml)
                        .HasForeignKey(o => o.OrderXmlId)
                        .WillCascadeOnDelete(true);           
                }

            }

    public class OrderXmlItemConfiguration : EntityTypeConfiguration<OrderXmlItem>
    {
        public OrderXmlItemConfiguration()
        {
            HasKey(o => o.OxI_Id);

            Property(p => p.OxI_Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            Property(p => p.OxI_PRODUCT).IsRequired();
            Property(p => p.OxI_ORDERLINE).IsRequired();
            Property(p => p.OxI_QUANTITY).IsRequired();
            Property(p => p.OxI_TYPE).IsRequired();
            Property(p => p.OxI_CURDIR).IsRequired();
            Property(p => p.OxI_CURWIDTH).IsRequired();
            Property(p => p.OxI_CURHEIGHT).IsRequired();
            Property(p => p.OxI_WORKMETH).IsRequired();
            Property(p => p.OxI_FOLDTYPE).IsRequired();
            Property(p => p.OxI_FOLDFACT).IsRequired();
            Property(p => p.OxI_PACKWLEFT).IsRequired();
            Property(p => p.OxI_PACKWRIGHT).IsRequired();
            Property(p => p.OxI_BARCODE).IsRequired();


            HasRequired(i => i.SewingCardBundle)
                .WithRequiredPrincipal( s=> s.OrderXmlItem)
                .WillCascadeOnDelete(true);


        }

    }

public class SewingCardBundleConfiguration : EntityTypeConfiguration<SewingCardBundle>
    {
        public SewingCardBundleConfiguration()
        {

            HasKey(s => s.SwC_Id);

            HasMany(s=>s.FlamanSewingCards)
                .WithRequired(c=>c.SewingCardBundle)
                .WillCascadeOnDelete(true);

            HasMany(s => s.FlamandzkaBrytaSewingCards)
                .WithRequired(c => c.SewingCardBundle)
                .WillCascadeOnDelete(true);

            HasMany(s => s.OczkaBrytaSewingCards)
                .WithRequired(c => c.SewingCardBundle)
                .WillCascadeOnDelete(true);

            HasMany(s => s.OczkaSewingCards)
                .WithRequired(c => c.SewingCardBundle)
                .WillCascadeOnDelete(true);

            HasMany(s => s.WellenbandSewingCards)
                .WithRequired(c => c.SewingCardBundle)
                .WillCascadeOnDelete(true);

            HasMany(s => s.WellenbandBrytaSewingCards)
                .WithRequired(c => c.SewingCardBundle)
                .WillCascadeOnDelete(true);

            HasMany(s => s.TunelSewingCards)
                .WithRequired(c => c.SewingCardBundle)
                .WillCascadeOnDelete(true);

            HasMany(s => s.PodwiazkaSewingCards)
                .WithRequired(c => c.SewingCardBundle)
                .WillCascadeOnDelete(true);


        }
    }

1 个答案:

答案 0 :(得分:1)

我不确定你为什么要首先调用SaveChanges(不需要),但是一旦从数据库获取数据,上下文就会跟踪它们(即缓存它们)。

由于您未在查询中指定AsNoTrackingSaveChanges方法将尝试保存正在跟踪的实体,这将导致您的“主要密钥违规”异常。

要解决此问题,您只需指定AsNoTracking

即可
var dupesInDb = _context
   .OrdersXml.Include(o=>o.OrderXmlItems)
   .Where(o => o.OrX_ORDERNR.Contains(newOrderXml.OrX_ORDERNR))
   .AsNoTracking()
   .ToList();