继承自 DbSet<TEntity> in Entity Framework Code first NullReference

Inherit from DbSet<TEntity> in Entity Framework Code first NullReference

我想对每个添加元素的动作执行nlog。 所以当我做 myContext.Society.Add() 时,我想记录一些东西。 我创建了一个 class DbSetExtension 并修改上下文 StockContext 以使用 DbSetExtension<T> 而不是 DbSet.

public class DbSetExtension<T> : DbSet<T> where T : class
{
    public override T Add(T entity)
    {
        LoggerInit.Current().Trace("Add Done");
        return base.Add(entity);
    }
}

当我启动程序时,我注意到我访问了 myContext.Society.Add。 社会是空的。所以我想我的 class DbSetExtension 遗漏了一些东西,但我没有找到。

public class StockContext : DbContext
{

    public StockContext()
        : base("StockContext")
    {
    }

    public DbSet<HistoricalDatas> HistoricalDatas { get; set; }
    public DbSet<Society> Society { get; set; }  

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();           
    }
}

你有什么想法, 问候, 亚历克斯

[更新] 代码允许添加。 如果我用 DbSet 替换 DbSetExtension,同样的代码可以工作。 所以我的假设是当我从 DbSet 继承时我错过了一些东西。

    public bool SetSymbols()
    {            
        CsvTools csvThreat = new CsvTools();
        List<Eoddata> currentEnum =
            csvThreat.ExtractData<Eoddata>(ConfigurationManager.GetString("FilePathQuotes", ""));
        currentEnum.ForEach(
            c =>
                {
                    //LoggerInit.Current().Trace("Add Done");
                    Sc.Society.Add(
                        new Society()
                        {
                            RealName = c.Description,
                            Symbol = String.Format("{0}.PA", c.Symbol),
                            IsFind = !String.IsNullOrEmpty(c.Description)
                        });
                });            
        if (Sc.SaveChanges() > 0)
            return true;
        return false;
    }

在我看来,你的方向完全错误。 DbContext 可以与 DbSet 一起使用,而不是与 DbSetExtension class 一起使用。它能够实例化 DbSet 类型的对象,而不是您自己的类型。这基本上就是您获得此异常的原因。修复它可能需要破解 EF 内部结构,我担心这个问题对您来说只是一个开始。相反,我建议您使用拦截器 classes 使用 EF 进行日志记录的一般方式。这里在文章Logging and Intercepting Database Operations末尾有详细解释。一般来说,这种方法对你来说更有利。为什么?因为 DbContext 只是与 db 通信的中间人。在日志中,您通常关心数据库及其数据发生了什么。如果不延迟调用 SaveChanges,则在 DbSet 上调用 Add 方法可能根本没有任何效果。相反,查询拦截器允许您严格记录与数据库的交互。根据发送到数据库的查询,您可以区分发生了什么。

但是如果你坚持你的方法,我建议你使用扩展方法而不是从 DbSet 派生:

public static class DbSetExtensions
{
    public static T LoggingAdd<T>(this DbSet<T> dbSet, T entity)
    {
        LoggerInit.Current().Trace("Add Done");
        return dbSet.Add(entity);
    }
}

并这样称呼它:

context.Stock.LoggingAdd(entity);