0

好的,我不确定我在这里错过了什么,所以就这样吧。我正在使用实体框架填充 MySQL 数据库。我要么更新或向数据库添加新记录。首先,我搜索一条记录,如果它返回 null,那么我知道我必须添加记录。如果搜索返回记录,那么我对记录进行更改。

所以这是一个简短的总结。最初我将配置属性保留为默认值并在需要时运行 SaveChanges(),但是我阅读以加快我的程序将它们设置为 false 更好。当我关闭这些时,我的问题发生了:

context.Configuration.AutoDetectChangesEnabled = false;
context.Configuration.ValidateOnSaveEnabled = false;

下面是给我带来麻烦的代码。 一旦我运行 Attach 方法并设置 Modified 状态,然后运行WFContext.SaveChanges()​​System.Data.Entity.Infrastructure.DbUpdateException 就会抛出。 我以为我做得对吗?显然不是...

 if (add)
 {
    WFContext.SecuritiesEntitySet.Add(security);
 }
 else
 {
    WFContext.SecuritiesEntitySet.Attach(security);
    WFContext.Entry(security).State = EntityState.Modified;
 }

我到底在这里想念什么?

这是跟踪:

A first chance exception of type 'System.Data.Entity.Infrastructure.DbUpdateException' occurred in EntityFramework.dll
   at System.Data.Entity.Internal.InternalContext.SaveChanges()
   at System.Data.Entity.Internal.LazyInternalContext.SaveChanges()
   at System.Data.Entity.DbContext.SaveChanges()
   at MyContext.SaveChanges() in MyContext.cs:line 24
   at ContextConnection.RecreateWFContext() in ContextConnection.cs:line 26
   at AbstractRecords.CheckRecordCount() in AbstractRecords.cs:line 46
   at SecuritiesRecord.Parser() SecuritiesRecord.cs:line 74
An error occurred while updating the entries. See the inner exception for details.

您在跟踪及以后看到的内容的简要细分:

  • ContextConnection 是一个静态类,用于管理与 MyContext 的连接。RecreateWFContext 释放当前上下文,然后再次初始化。
  • AbstractRecords 在所有记录类都可以使用的方法中提供属性。
  • SecuritiesRecord.Parser 解析字符串并加载安全对象中的所有属性。

这是 SecurityInfo 类,security在上面的问题代码示例中实例化并引用了它。

public partial class SecurityInfo
    {
        public System.DateTime ImportDate { get; set; }
        public string CUSIP { get; set; }
        public string Symbol { get; set; }
        public string SecurityType { get; set; }
        public Nullable<System.DateTime> PriceDate { get; set; }
        public Nullable<decimal> PriceClose { get; set; }
        public Nullable<decimal> DividendRate { get; set; }
        public Nullable<System.DateTime> ExDate { get; set; }
        public Nullable<System.DateTime> PayableDate { get; set; }
        public string PaymentFrequency { get; set; }
        public Nullable<System.DateTime> FirstCallDate { get; set; }
        public Nullable<decimal> FirstCallRate { get; set; }
        public Nullable<System.DateTime> SecondCallDate { get; set; }
        public Nullable<decimal> SecondCallRate { get; set; }
        public Nullable<int> Industry { get; set; }
        public Nullable<decimal> EquityDividendRate { get; set; }
        public Nullable<System.DateTime> EquityRecordDate { get; set; }
        public Nullable<System.DateTime> EquityPayableDate { get; set; }
        public Nullable<System.DateTime> EquityExDividendDate { get; set; }
        public string EquitySplitRate { get; set; }
        public string OSISymbol { get; set; }
        public Nullable<System.DateTime> OSIExpirationDate { get; set; }
        public string OSIOptionType { get; set; }
        public Nullable<decimal> OSIStrikePrice { get; set; }
        public Nullable<decimal> OptionContractLotSize { get; set; }
        public Nullable<decimal> AnnualCouponRate { get; set; }
        public Nullable<System.DateTime> MaturityDate { get; set; }
        public Nullable<System.DateTime> PaymentDate { get; set; }
        public Nullable<decimal> GNMAFactor { get; set; }
        public string SPRating { get; set; }
        public string MoodyRating { get; set; }
    }

更新 我把这些拿出来:

context.Configuration.AutoDetectChangesEnabled = false;
context.Configuration.ValidateOnSaveEnabled = false;

我仍然得到同样的例外。我认为它必须在 ContextConnection 类中。这是它的样子:

public static class ContextConnection
{
    private static MyContext WFContext;

    public static MyContext GetWFContext()
    {
        return WFContext;
    }

    public static void NewWFContext()
    {
        WFContext = new MyContext();
        //WFContext.Configuration.AutoDetectChangesEnabled = false;
        //WFContext.Configuration.ValidateOnSaveEnabled = false;  
    }
    public static void RecreateWFContext()
    {
        WFContext.SaveChanges();
        DisposeWFContext();
        NewWFContext();
    }

    public static void DisposeWFContext()
    {
        WFContext.Dispose();
    }
}

当程序启动时,我调用ContextConnection.NewWFContext()并在 try-catch 块的 finally 部分调用DisposeWFContext

只是为了好衡量。这是 AbstractRecords 类中的方法,当 100 条记录已更改时,我在其中重新创建上下文:

protected void CheckRecordCount()
{
    RecordsChangedCount++;

    if (RecordsChangedCount == 100)
    {
        ContextConnection.RecreateWFContext();
        RecordsChangedCount = 0;
    }
}

任何帮助将不胜感激!

谢谢,贾斯汀

4

1 回答 1

1

我的解决方案

感谢大家帮助我。昨天终于弄明白了。交易是对于某些表,例如 Securities 表,我检查记录是否已经存在,如果不存在,则添加记录。如果记录确实存在,那么我更新记录。因此,您可以看到,如果我在每 100 条记录更改后等待将更改推送到数据库并且我正在检查数据库是否已添加记录,这可能是一个问题。所以基本上我试图添加两条具有相同唯一键的记录,只有在执行 SaveChanges 时,程序才发现有重复的记录并抛出异常。

所以在此期间。我不会在 100 条记录之后处理我的上下文,而是在我完成将文本文件导入我的 MySQL 数据库之后才处理它。将来我必须编写一些可以处理添加/更新的逻辑,但现在只是这样做:

context.Configuration.AutoDetectChangesEnabled = false;
context.Configuration.ValidateOnSaveEnabled = false;

仅仅这样做就大大减少了导入时间,从大约 13 分钟到大约 1 分钟,用于 9,000 条记录。 所以现在这已经足够了

谢谢您的帮助!这一切都让我弄清楚了这个问题。

贾斯汀

于 2013-10-31T13:13:28.307 回答