英文:
Inserting a dependent entity while inserting the principal entity with Entity Framework
问题
以下是你要翻译的代码部分:
Firstly, these are my entities.
public class Restaurant : Entity
{
public string Name { get; set; }
public int OwnerId { get; set; }
public virtual Owner Owner { get; set; }
public virtual Menu Menu { get; set; }
public Restaurant()
{
Menu = new Menu();
}
}
public class Menu : Entity
{
public int RestaurantId { get; set; }
public virtual ICollection<Campaign> Campaigns { get; set; }
public virtual ICollection<Category> Categories { get; set; }
public virtual Restaurant Restaurant { get; set; }
public Menu()
{
Campaigns = new HashSet<Campaign>();
Categories = a new HashSet<Category>();
}
}
Also they have one to one relationship. Declared as:
modelBuilder.Entity<Restaurant>(r =>
{
r.HasOne(r => r.Owner)
.WithMany()
.HasForeignKey(r => r.OwnerId);
r.HasOne(r => r.Menu)
.WithOne(m => m.Restaurant)
.HasForeignKey<Menu>(m => m.RestaurantId);
});
modelBuilder.Entity<Menu>(m =>
{
m.HasMany(m => m.Campaigns)
.WithOne(c => c.Menu)
.HasForeignKey(x => x.MenuId);
m.HasMany(m => m.Categories)
.WithOne(c => c.Menu)
.HasForeignKey(c => c.MenuId);
m.HasOne(m => m.Restaurant)
.WithOne(r => r.Menu);
});
The problem is I am creating a Restaurant when I get the CreateRestaurantCommand request. Inside of it:
public class CreateRestaurantCommandHandler : IRequestHandler<CreateRestaurantCommand, CreatedRestaurantResponseDto>
{
private readonly IRestaurantRepository _restaurantRepository;
private readonly RestaurantBusinessRules _restaurantBusinessRules;
public CreateRestaurantCommandHandler(IRestaurantRepository restaurantRepository, RestaurantBusinessRules restaurantBusinessRules)
{
_restaurantRepository = restaurantRepository;
_restaurantBusinessRules = restaurantBusinessRules;
}
public async Task<CreatedRestaurantResponseDto> Handle(CreateRestaurantCommand request, CancellationToken cancellationToken)
{
await _restaurantBusinessRules.DoesOwnerExistAndHaveRestaurantWithSameName(request.OwnerId, request.RestaurantName);
Restaurant restaurant = new()
{
Name = request.RestaurantName,
OwnerId = request.OwnerId,
};
Restaurant createdRestaurant = await _restaurantRepository.CreateAsync(restaurant);
CreatedRestaurantResponseDto response = new()
{
Id = createdRestaurant.Id,
Name = createdRestaurant.Name,
OwnerId = createdRestaurant.OwnerId
};
return response;
}
}
Everythink works perfect. However the created Menu inside of the restaurant's constructor is not pushed to the db.
This my CreateAsync method.
public async Task<TEntity> CreateAsync(TEntity entity)
{
Context.Entry(entity).State = EntityState.Added;
await Context.SaveChangesAsync();
return entity;
}
I have tried empty constructor creating the menu inside of curly brackets and changing the configuration made in dbcontext but these didn't solve the problem.
希望这能帮助你解决问题。
英文:
Firstly, these are my entities.
public class Restaurant : Entity
{
public string Name { get; set; }
public int OwnerId { get; set; }
public virtual Owner Owner { get; set; }
public virtual Menu Menu { get; set; }
public Restaurant()
{
Menu = new Menu();
}
}
public class Menu : Entity
{
public int RestaurantId { get; set; }
public virtual ICollection<Campaign> Campaigns { get; set; }
public virtual ICollection<Category> Categories { get; set; }
public virtual Restaurant Resturant { get; set; }
public Menu()
{
Campaigns = new HashSet<Campaign>();
Categories = new HashSet<Category>();
}
}
Also they have one to one relationship. Declared as:
modelBuilder.Entity<Restaurant>(r =>
{
r.HasOne(r => r.Owner)
.WithMany()
.HasForeignKey(r =>r.OwnerId);
r.HasOne(r => r.Menu)
.WithOne(m => m.Resturant)
.HasForeignKey<Menu>(m => m.RestaurantId);
});
modelBuilder.Entity<Menu>(m =>
{
m.HasMany(m => m.Campaigns)
.WithOne(c => c.Menu)
.HasForeignKey(x => x.MenuId);
m.HasMany(m => m.Categories)
.WithOne(c => c.Menu)
.HasForeignKey(c => c.MenuId);
m.HasOne(m => m.Resturant)
.WithOne(r => r.Menu);
});
The problem is I am creating a Restaurant when I get the CreateRestourantCommand request. Inside of it:
public class CreateRestaurantCommandHandler : IRequestHandler<CreateRestaurantCommand, CreatedRestaurantResponseDto>
{
private readonly IRestaurantRepository _restaurantRepository;
private readonly RestaurantBusinessRules _restaurantBusinessRules;
public CreateRestaurantCommandHandler(IRestaurantRepository restaurantRepository, RestaurantBusinessRules restaurantBusinessRules)
{
_restaurantRepository = restaurantRepository;
_restaurantBusinessRules = restaurantBusinessRules;
}
public async Task<CreatedRestaurantResponseDto> Handle(CreateRestaurantCommand request, CancellationToken cancellationToken)
{
await _restaurantBusinessRules.DoesOwnerExistAndHaveRestaurantWithSameName(request.OwnerId, request.RestaurantName);
Restaurant restaurant = new()
{
Name = request.RestaurantName,
OwnerId = request.OwnerId,
};
Restaurant createdRestaurant = await _restaurantRepository.CreateAsync(restaurant);
CreatedRestaurantResponseDto response = new()
{
Id = createdRestaurant.Id,
Name = createdRestaurant.Name,
OwnerId = createdRestaurant.OwnerId
};
return response;
}
}
Everythink works perfect. However the created Menu inside of the restaurant's constructor is not pushed to the db.
This my CreateAsync method.
public async Task<TEntity> CreateAsync(TEntity entity)
{
Context.Entry(entity).State = EntityState.Added;
await Context.SaveChangesAsync();
return entity;
}
I have tried empty constructor creating the menu inside of curly brackets and changing the configuration made in dbcontext but these didn't solve the problem.
答案1
得分: 2
"EntityState = EntityState.Added"不会设置相关实体的状态,它只是将它们关联,但状态保持未修改。要确保实体及其相关实体被视为添加,请使用"Context.Set
public async Task<TEntity> CreateAsync(TEntity entity)
{
Context.Set<TEntity>.Add(entity);
await Context.SaveChangesAsync();
return entity;
}
我不建议使用通用存储库,而是建议使用强类型存储库,这样您可以根据需要处理特定的关系,并提供基本功能,如工厂方法,而不是由调用代码构造实体。
英文:
The short answer is that EntityState = EntityState.Added
does not set the state of related entities, it associates them but leaves them Unmodified. Use Context.Set<TEntity>().Add(entity)
to ensure the entity and related are treated as additions. This Will likely cause you issues down the road because in adding entities there will likely be times where you want to Add new related entities, but other times you want to Associate related entities. Unless those associated entities are tracked by the DbContext this can result in duplicate index violations as EF tries to insert them, or inserting duplicate data with new PKs.
public async Task<TEntity> CreateAsync(TEntity entity)
{
Context.Set<TEntity>.Add(entity);
await Context.SaveChangesAsync();
return entity;
}
I do not recommend using Generic Repositories, but instead strongly typed ones so you can deal with specific relationships as you need, and provide base functionality like Factory methods rather than having calling code constructing entities.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论