/// <summary> /// Inserts or updates the specified domain entity and any entities within its graph. The calling client will need /// to set the appropriate state on the domain entities within the graph. /// </summary> /// <param name="entity">The entity.</param> public void InsertOrUpdateGraph(TEntity entity) { // Get a list of entities currently being tracked, as don't want to reprocess them in the code below IList <DbEntityEntry> trackedEntrys = this.DbContext.ChangeTracker.Entries().ToList(); // Adding the entity will mark attach all entities in the graph to the dbContext. It will also ensure all FK relationships are set correctly. this.dbSet.Add(entity); var changedEntities = this.DbContext.ChangeTracker.Entries(); // For any entities being tracked, tell the context about the entities state. foreach (DbEntityEntry entry in changedEntities) { if (trackedEntrys.Contains(entry)) { // This entry was already in the tracker before this method call, so ignore continue; } if (entry.Entity is IEntityWithState) { IEntityWithState entityWithState = (IEntityWithState)entry.Entity; if (entityWithState.State == State.NotSet) { // If the entity states have not been set, then use a convention to determine then entity state based on whether // the entity has an Id entityWithState.State = CalculateEntityStateBasedOnConvention(entry.Entity); } // Convert the domain representation of state to the entity framework enumeration entry.State = GetEntityState(entityWithState.State); } } if (this.unitOfWork != null && this.unitOfWork.Transaction != null) { this.DbContext.SaveChanges(); } this.ClearCache(); }
public void InsertGraphForNewAggregateRootEntityAndChildrenWhereChildrenSpecifiedAsUnchanged() { // Arrange const int expectedSimpleId1 = 10; const int expectedSimpleId2 = 11; const int expectedSimpleId3 = 12; FakeDbContext dbContext = new FakeDbContext(); AggregateRootEntityRepository entityRepository = new AggregateRootEntityRepository(dbContext); // Create an aggregate root where one of the 'AnotherSimpleEntity' already exist (i.e. has a primary key) AggregateRootEntity aggregateRootEntity = new AggregateRootEntity { SomeOtherProperty = "Some other property", SimpleEntity = new SimpleEntity { Id = expectedSimpleId1, SomeProperty = "Some property", State = State.Unchanged }, OtherSimpleEntities = new List <AnotherSimpleEntity> { new AnotherSimpleEntity { Id = expectedSimpleId2, SomeProperty = "Child property 1", State = State.Unchanged }, new AnotherSimpleEntity { Id = expectedSimpleId3, SomeProperty = "Child property 2", State = State.Unchanged }, } }; // Act entityRepository.InsertOrUpdateGraph(aggregateRootEntity); // Assert Assert.IsNotNull(entityRepository.DbContext); // The AggregateRoot and its children should all be added to the context and all have a state of 'Added' Assert.AreEqual(4, entityRepository.DbContext.ChangeTracker.Entries().Count()); entityRepository.DbContext.ChangeTracker.Entries().ToList().ForEach(entry => { IEntityWithState <int> entityWithState = (IEntityWithState <int>)entry.Entity; Assert.AreEqual(entityWithState.Id == default(int) ? EntityState.Added : EntityState.Unchanged, entry.State); }); }