[英]Entity Framework update lookup table is adding items to another table
查詢表有問題。 我有一個表格,可以讓我從團隊的列表中選擇顏色。 更新方法如下所示:
[HttpPut]
[Route("")]
/// <summary>
/// Update a team
/// </summary>
/// <param name="model">The team model</param>
/// <returns>Nothing</returns>
public async Task<IHttpActionResult> Update(TeamBindingViewModel model)
{
// If our model is invalid, return the errors
if (!ModelState.IsValid)
return BadRequest(ModelState);
// Get our current team
var team = await this.service.GetAsync(model.Id, "Colours");
// Make changes to our team
team.Name = model.Name;
team.Sport = model.Sport;
// Find out which colours need adding and removing
var coloursToRemove = GetDifference(team.Colours, model.Colours);
var coloursToAdd = GetDifference(model.Colours, team.Colours);
// Loop through our colours to remove and remove them
if (coloursToRemove.Count() > 0)
foreach (var colour in coloursToRemove)
team.Colours.Remove(colour);
// Loop through the colours to add and add them
if (coloursToAdd.Count() > 0)
foreach (var colour in coloursToAdd)
team.Colours.Add(colour);
// Update the team
this.service.Update(team);
// Save the database changes
await this.unitOfWork.SaveChangesAsync();
// Return Ok
return Ok(model);
}
private IList<Colour> GetDifference(IList<Colour> firstList, IList<Colour> secondList)
{
// Create a new list
var list = new List<Colour>();
// Loop through the first list
foreach (var first in firstList)
{
// Create a boolean and set to false
var found = false;
// Loop through the second list
foreach (var second in secondList)
{
// If the first item id is the same as the second item id
if (first.Id == second.Id)
{
// Mark it has being found
found = true;
}
}
// After we have looped through the second list, if we haven't found a match
if (!found)
{
// Add the item to our list
list.Add(first);
}
}
// Return our differences
return list;
}
如果我在unitOfWork.SaveChangesAsync()上設置一個斷點,那么我可以看到團隊顏色正在使用數據庫中已經存在的現有顏色(所有ID都匹配。但是一旦執行SaveChangesAsync ,它就會在Colors中創建一個新行與我剛剛選擇的顏色重復的表格,我不希望它創建新的行,我希望它使用選擇的顏色。
我不確定如何提供更多信息; 我希望這足以為某人提供幫助的描述!
更新
因此,我決定查看生成的SQL。 我的“ 顏色”表中有一個看起來像這樣的顏色 :
10紅色(Pms200)ff0000
因此, Id為10 , 名稱為Red(Pms200) , 十六進制為ff0000 。 如果我在編輯團隊時選擇該顏色,然后按提交。 它運行上面顯示的Update方法,並且通過在構造函數中添加以下行,我更改了DbContext來記錄sql:
this.Database.Log = s => Debug.WriteLine(s);
因此,當執行SaveChangesAsync代碼時,將生成以下SQL:
Started transaction at 13/04/2015 12:25:03 +01:00
UPDATE [dbo].[Teams]
SET [Name] = @0, [Sport] = @1
WHERE ([Id] = @2)
-- @0: 'Testing' (Type = String, Size = -1)
-- @1: 'ultimate-frisbee' (Type = String, Size = -1)
-- @2: '1' (Type = Int32)
-- Executing asynchronously at 13/04/2015 12:25:03 +01:00
-- Completed in 5 ms with result: 1
INSERT [dbo].[Colours]([Name], [Hex])
VALUES (@0, @1)
SELECT [Id]
FROM [dbo].[Colours]
WHERE @@ROWCOUNT > 0 AND [Id] = scope_identity()
-- @0: 'Red (Pms200)' (Type = String, Size = -1)
-- @1: 'ff0000' (Type = String, Size = -1)
-- Executing asynchronously at 13/04/2015 12:25:03 +01:00
-- Completed in 1 ms with result: SqlDataReader
INSERT [dbo].[TeamColours]([TeamId], [ColourId])
VALUES (@0, @1)
-- @0: '1' (Type = Int32)
-- @1: '43' (Type = Int32)
-- Executing asynchronously at 13/04/2015 12:25:03 +01:00
-- Completed in 1 ms with result: 1
Committed transaction at 13/04/2015 12:25:03 +01:00
Closed connection at 13/04/2015 12:25:03 +01:00
現在的問題是,它應該只在TeamColours表中插入內容,而不是在Colors表中插入內容。 我不知道為什么...
由於有人要求查看我的UnitOfWork類,因此它是:
public class UnitOfWork<TContext> : IUnitOfWork where TContext : DbContext, new()
{
private readonly DbContext context;
private Dictionary<Type, object> repositories;
public DbContext Context { get { return this.context; } }
public UnitOfWork()
{
this.context = new TContext();
repositories = new Dictionary<Type, object>();
}
public IRepository<TEntity> GetRepository<TEntity>() where TEntity : class
{
if (repositories.Keys.Contains(typeof(TEntity)))
return repositories[typeof(TEntity)] as IRepository<TEntity>;
var repository = new Repository<TEntity>(context);
repositories.Add(typeof(TEntity), repository);
return repository;
}
public async Task SaveChangesAsync()
{
try
{
await this.context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException ex)
{
ex.Entries.First().Reload();
}
}
public void Dispose()
{
this.context.Dispose();
}
}
盡管我確定這不是導致問題的原因。
嘗試這個
public async Task<IHttpActionResult> Update(TeamBindingViewModel model)
{
// If our model is invalid, return the errors
if (!ModelState.IsValid)
return BadRequest(ModelState);
// Get our current team
var team = await this.service.GetAsync(model.Id, "Colours");
// Make changes to our team
team.Name = model.Name;
team.Sport = model.Sport;
//remove
foreach (var colour in team.Colours.ToList())
{
if (!model.Colours.Any(c => c.Id == colour.Id))
team.Colours.Remove(colour);
}
//add
foreach (var colour in model.Colours)
{
if (!team.Colours.Any(c => c.Id == colour.Id))
team.Colours.Add(colour);
}
// Update the team
this.service.Update(team);
// Save the database changes
await this.unitOfWork.SaveChangesAsync();
// Return Ok
return Ok(model);
}
Model.Colors沒有關聯上下文。 因此,您的Db上下文會嘗試添加新的。
1-從存儲庫獲取顏色
var newColours = repository.ListColours(model.Colors.Select(m=>m.Id));
2-為團隊分配新顏色
team.Colours = newColours;
this.service.Update(team);
await this.unitOfWork.SaveChangesAsync();
EF將自動執行刪除和添加操作。
我尚未測試此代碼。 但是我希望EntityFramework可以比我想象的更聰明。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.