【问题标题】:EF Code First An entity object cannot be referenced by multiple instances of IEntityChangeTrackerEF Code First 实体对象不能被多个 IEntityChangeTracker 实例引用
【发布时间】:2015-07-25 07:52:30
【问题描述】:

我有一个有很多答案的问题。我得到的例外是:

一个实体对象不能被多个 IEntityChangeTracker 实例引用。

当我在网上冲浪和堆叠流页面时,我已经达到这一点,即 DbContext 的实例在每个 UnitOfWork 中应该只有一个,否则必须分离前一个。听起来很合理!但是,我的问题是我不知道我必须在我的代码中的哪个位置(发布在下面)进行修改。 我一直在尝试使用通用存储库和工作单元模式加上 EF 代码优先方法。

public abstract class Repository<T> : IRepository<T> where T : BaseEntity
{
    protected DbContext EntityContext;
    protected readonly IDbSet<T> DbSet;

    protected Repository(DbContext context)
    {
        EntityContext = context;
        DbSet = context.Set<T>();
    }

    public virtual IEnumerable<T> GetList()
    {
        return DbSet.AsEnumerable();
    }

    public virtual T Add(T entity)
    {
        return DbSet.Add(entity);
    }
}

通用工作单元:

public sealed class UnitOfWork : IUnitOfWork
{
    private DbContext _context;

    public UnitOfWork(DbContext context)
    {
        _context = context;
    }

    public int Commit()
    {
        return _context.SaveChanges();
    }

    private void Dispose(bool disposing)
    {
        if (!disposing) return;
        if (_context == null) return;

        _context.Dispose();
        _context = null;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

客户端存储库

public class ClientRepository : Repository<Client>, IClientRepository
{
    public ClientRepository(DbContext context)
        : base(context)
    {

    }

    public override Client Add(Client entity)
    {
        return DbSet.Add(entity); // <-- Here the exception comes
    }
}

这是放置在“DataGenerator”项目中的“GenerateClients”方法的主要部分。

var countries = container.Resolve<ICountryService>().GetList().ToList();

        if (!countries.Any())
        {
            throw new InvalidDataGeneratorException(Strings.NoCountryToCreateClient);
        }

        var clientService = container.Resolve<IClientService>();

        clientService.Create(new Client
                             {
                                 Name = "Dell",
                                 CountryId = countries[0].Id,
                                 Country = countries[0],
                                 AddressLineOne = "76-98 Victoria Street",});

这里是使用 ClientRepository 的 ClientService:

public class ClientService : Service<Client>, IClientService
{
    IUnitOfWork UnitOfWork { get; set; }
    private readonly IClientRepository _clientRepository;
    private readonly ICalculatorService _calculatorService;

    public ClientService(IClientRepository clientRepository,
        IUnitOfWork unitOfWork,
        ICalculatorService calculatorService)
        : base(clientRepository, unitOfWork)
    {
        UnitOfWork = unitOfWork;
        _calculatorService = calculatorService;
        _clientRepository = clientRepository;
    }

    public override void Create(Client client)
    {
        _clientRepository.Add(client);
        _clientRepository.Save();
    }

    }

请注意,为了尽量减少问题的长度,部分方法已被删除。

实际上,当我运行我的控制台类型的数据生成器项目时,在添加客户端之前,已经添加了一些国家没有问题,但是当涉及到客户端服务时,它会进入 ClientRepository,引发异常。

我不知道应该在哪里进行修改以避免异常。非常感谢

【问题讨论】:

  • 引发错误的调用代码是什么样的
  • 我不知道这是否与问题有关,但您在 UnitOfWork 中的 IDisposable 实现与正确的模式相去甚远。例如,你没有析构函数(或者只是从代码示例中离开?),所以 GC.SupressFinalize 没有意义......请谷歌搜索 IDisplosable 设计模式。
  • @3dd:如果我正确理解了您的意思,则调用代码是我添加到问题中的代码部分(最后一部分)。首先,我获取国家/地区列表,然后为每个国家/地区生成一个新客户。
  • @g.pickardou:我猜你所说的也可能有问题。实际上,Resharper 也告诉我你提到的内容。我不知道,但如果我纠正它,可能会有所帮助
  • 我的意思是使用ClientRepository 的代码是什么样的

标签: c# entity-framework-6 repository-pattern unit-of-work


【解决方案1】:

客户是否与国家/地区有关系,您是否将其添加为Client.Country = RELATED_COUNTRY,也许它试图将同一个国家/地区添加两次,我通常使用Client.CountryId = ID_OF_COUNTRY

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-01
    • 2011-10-12
    • 1970-01-01
    相关资源
    最近更新 更多