实体框架 4. 连接表。不需要任何操作时实体框架执行插入
我有一个数据库设置如下: -
Person Table
Hobby Table
Game Table
GameInfo Table
Person [1 - M] Hobby [1 - M] Game [M - 1] GameInfo
Game
只是来自 Hobby
的加入到 GameInfo
我遇到了一个问题,我将获取具有 Collection
的 Person
并将其添加到此集合中(即我只是更新链接,不想插入新的 GameInfo
)。
调用 SaveChanges()
EntityFramework 将插入链接以及插入新的 GameInfo
,这不是我想要的结果。
我已经查看了 Entry().State 等,但问题是我处理 Person
的更新的位置在上下文之外。
我基本上是获取一个 Person
使用我知道已经存在的 Id 创建一个新的 Game
,然后调用 SaveChanges()
并期望它只会插入到 GameInfo 表中,而不是 GameInfo 表中
编辑 1:代码示例 - 编辑 2 的排序
public void Save(Profile profile)
{
using (GDContext context = GetContext())
{
DataProfile dataProfile = context.Profiles.Single(u => u.ProfileId == profile.Id);
ProfileHandler.HandleDataModelChanges(dataProfile, profile);
context.SaveChanges();
}
}
public override void HandleDataModelChanges(DataProfile dataModel, Profile model)
{
dataModel.ProfileId = model.Id;
dataModel.FirstName = model.FirstName;
dataModel.LastName = model.LastName;
dataModel.DateOfBirth = model.DateOfBirth;
dataModel.Email = model.Email;
foreach(var hobby in model.Hobbies)
{
DataHobby dataHobby = dataModel.Hobbies.SingleOrDefault(p => p.HobbyId == hobby.HobbyId);
if (dataHobby == null)
{
dataHobby = new DataHobby();
}
HobbyHandler.HandleDataModelChanges(dataHobby, hobby);
}
}
public override void HandleDataModelChanges(DataHobby dataModel, Hobby model)
{
dataModel.HobbyId = model.Id;
HandleGames(dataModel, model);
HandleCrafts(dataModel, model);
HandleCollections(dataModel, model);
}
private void HandleGames(DataHobby dataModel, Hobby model)
{
IEnumerable<DataGame> gamesToRemove = dataModel.Games.Where(g => !model.Games.Any(ds => ds.Id == g.GameId)).ToArray();
foreach (var game in gamesToRemove)
{
dataModel.Games.Remove(game);
}
foreach (var game in model.Games)
{
if (!dataModel.Games.Any(e => e.GameId == game.Id))
{
DataGame dataGame = new DataGame();
dataGame.GameId = game.Id;
dataGame.GameName = game.Name;
dataModel.Games.Add(dataGame);
}
}
}
- 上下文配置
this.Configuration.LazyLoadingEnabled = false;
this.Configuration.AutoDetectChangesEnabled = true;
public GameInfoConfiguration()
{
HasKey(x => x.GameId);
ToTable("GameData");
}
public PersonConfiguration()
{
HasKey(x => x.PersonId);
ToTable("Person");
}
public HobbyConfiguration()
{
HasKey(x => x.HobbyId);
HasRequired(x => x.Person).WithMany(x => x.Hobbies);
HasMany(x => x.Games).WithMany(g => g.Hobbies).Map(x => x.MapLeftKey("HobbieId").MapRightKey("GameId").ToTable("PersonGame"));
ToTable("HobbyGame");
}
I have a database setup with the following: -
Person Table
Hobby Table
Game Table
GameInfo Table
Person [1 - M] Hobby [1 - M] Game [M - 1] GameInfo
Game
is just a join from Hobby
to GameInfo
I am having an issue whereby I would fetch Person
which has a Collection<Game>
and add to this collection (i.e. I am just updating links, not wanting to insert new GameInfo
).
Upon Calling SaveChanges()
EntityFramework will insert the links AS WELL AS inserting new GameInfo
, which is not my desired result.
I have looked at Entry().State etc but the problem is where I am handling the updates of my Person
is outside of the context.
I am basically fetching a Person
creating a new Game
with Ids that I know exist already and then calling the SaveChanges()
and would expect that it would just insert into the Game
Table, not the GameInfo table
EDIT 1: Code Sample - sort of
public void Save(Profile profile)
{
using (GDContext context = GetContext())
{
DataProfile dataProfile = context.Profiles.Single(u => u.ProfileId == profile.Id);
ProfileHandler.HandleDataModelChanges(dataProfile, profile);
context.SaveChanges();
}
}
public override void HandleDataModelChanges(DataProfile dataModel, Profile model)
{
dataModel.ProfileId = model.Id;
dataModel.FirstName = model.FirstName;
dataModel.LastName = model.LastName;
dataModel.DateOfBirth = model.DateOfBirth;
dataModel.Email = model.Email;
foreach(var hobby in model.Hobbies)
{
DataHobby dataHobby = dataModel.Hobbies.SingleOrDefault(p => p.HobbyId == hobby.HobbyId);
if (dataHobby == null)
{
dataHobby = new DataHobby();
}
HobbyHandler.HandleDataModelChanges(dataHobby, hobby);
}
}
public override void HandleDataModelChanges(DataHobby dataModel, Hobby model)
{
dataModel.HobbyId = model.Id;
HandleGames(dataModel, model);
HandleCrafts(dataModel, model);
HandleCollections(dataModel, model);
}
private void HandleGames(DataHobby dataModel, Hobby model)
{
IEnumerable<DataGame> gamesToRemove = dataModel.Games.Where(g => !model.Games.Any(ds => ds.Id == g.GameId)).ToArray();
foreach (var game in gamesToRemove)
{
dataModel.Games.Remove(game);
}
foreach (var game in model.Games)
{
if (!dataModel.Games.Any(e => e.GameId == game.Id))
{
DataGame dataGame = new DataGame();
dataGame.GameId = game.Id;
dataGame.GameName = game.Name;
dataModel.Games.Add(dataGame);
}
}
}
EDIT 2 - Context configuration
this.Configuration.LazyLoadingEnabled = false;
this.Configuration.AutoDetectChangesEnabled = true;
public GameInfoConfiguration()
{
HasKey(x => x.GameId);
ToTable("GameData");
}
public PersonConfiguration()
{
HasKey(x => x.PersonId);
ToTable("Person");
}
public HobbyConfiguration()
{
HasKey(x => x.HobbyId);
HasRequired(x => x.Person).WithMany(x => x.Hobbies);
HasMany(x => x.Games).WithMany(g => g.Hobbies).Map(x => x.MapLeftKey("HobbieId").MapRightKey("GameId").ToTable("PersonGame"));
ToTable("HobbyGame");
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
好吧,我仍然不明白你在哪里使用
GameInfo
- 你的描述绝对与你的代码不符。通过查看您的代码,我猜问题出在这样的代码片段中:这将始终插入一个新的
Game
- 您告诉 EF 插入一个新的Game
。如果您想添加现有的游戏
,您必须执行以下操作:Well I still don't see where you work with
GameInfo
- your description absolutely doesn't correspond with your code. By looking at your code I guess the problem will be in the snippet like this:This will always insert a new
Game
- you told EF to insert a newGame
. If you want to add existingGame
you must do:我认为我在这里犯的错误是,我正在处理
DataGame
,而实际上我应该处理的是一个 POCO 类来表示DataGame
和Hobby
就像一个HobbyGame
POCO。I think the mistake I have made here is that I am dealing with
DataGame
when really what I should be dealing with is a POCO class to represent the "join" betweenDataGame
andHobby
Like aHobbyGame
POCO.