所以, 我已经构建了一个存储库/服务应用程序,我已成功使用了一段时间。 我已经开始了一个新项目,在这个项目中,我有一个查找表附加到我的一个模型/实体。 该模型如下所示:
public class Team
{
public int Id { get; set; }
public string Name { get; set; }
public string Sport { get; set; }
public IList<Colour> Colours { get; set; }
}
我还有一个绑定的ViewModel,如下所示:
public class TeamBindingViewModel
{
public int Id { get; set; }
[Required] public string Name { get; set; }
[Required] public string Sport { get; set; }
public IList<ColourBindingViewModel> Colours { get; set; }
}
public class ColourBindingViewModel
{
public int Id { get; set; }
[Required] public string Name { get; set; }
[Required] public string Hex { get; set; }
}
在我的 dbContext 类中,我设置了这个:
public class DatabaseContext : DbContext
{
// Define our tables
public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; }
public DbSet<Colour> Colours { get; set; }
public DbSet<Team> Teams { get; set; }
/// <summary>
/// static constructor (only gets called once)
/// </summary>
static DatabaseContext()
{
// Create the database and insert our records
//Database.SetInitializer<DatabaseContext>(new DatabaseInitializer());
}
/// <summary>
/// Default constructor
/// </summary>
public DatabaseContext()
: base("DefaultConnection")
{
// Disable Lazy Loading
base.Configuration.LazyLoadingEnabled = false;
}
/// <summary>
/// Overrides the inherited OnModelCreated method.
/// </summary>
/// <param name="modelBuilder">The DbModelBuilder</param>
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Remove Cascading Delete
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
// Map the TeamColours table
modelBuilder.Entity<Team>()
.HasMany(m => m.Colours)
.WithMany()
.Map(m =>
{
m.MapLeftKey("TeamId");
m.MapRightKey("ColourId");
m.ToTable("TeamColours");
});
}
}
( nb:我已将其删除以便于阅读)
所以,我遇到的问题是当我尝试更新时,如果我尝试添加颜色,我会收到错误。 以下是我的基础知识库类:
public class Repository<T> : IDisposable, IRepository<T> where T : class
{
private readonly DbContext context;
private readonly DbSet<T> dbEntitySet;
public Repository(DbContext context)
{
if (context == null)
throw new ArgumentNullException("context");
this.context = context;
this.dbEntitySet = context.Set<T>();
}
public IQueryable<T> GetAll(params string[] includes)
{
IQueryable<T> query = this.dbEntitySet;
foreach (var include in includes)
query = query.Include(include);
return query;
}
public void Create(T model)
{
this.dbEntitySet.Add(model);
}
public void Update(T model)
{
this.context.Entry<T>(model).State = EntityState.Modified;
}
public void Remove(T model)
{
this.context.Entry<T>(model).State = EntityState.Deleted;
}
public void Dispose()
{
this.context.Dispose();
}
}
然后我有一个这样的基本服务类:
public class Service<T> where T : class
{
private readonly IRepository<T> repository;
protected IRepository<T> Repository
{
get { return this.repository; }
}
public Service(IUnitOfWork unitOfWork)
{
if (unitOfWork == null)
throw new ArgumentNullException("unitOfWork");
this.repository = unitOfWork.GetRepository<T>();
}
}
最后这是我的 TeamService 类:
/// <summary>
/// Team service handles all team related functions
/// </summary>
public class TeamService : Service<Team>
{
/// <summary>
/// Default constructor
/// </summary>
/// <param name="unitOfWork"></param>
public TeamService(IUnitOfWork unitOfWork)
: base(unitOfWork)
{
}
/// <summary>
/// Get all teams asynchronously
/// </summary>
/// <param name="includes">Eager loading includes</param>
/// <returns>A list of colours</returns>
public async Task<IList<Team>> GetAllAsync(params string[] includes)
{
return await this.Repository.GetAll(includes).ToListAsync();
}
/// <summary>
/// Get a team by id
/// </summary>
/// <param name="id">The id of the colour</param>
/// <param name="includes">Eager loading includes</param>
/// <returns>A colour</returns>
public async Task<Team> GetAsync(int id, params string[] includes)
{
var models = await this.GetAllAsync(includes);
return models.Where(model => model.Id == id).SingleOrDefault();
}
/// <summary>
/// Create a team
/// </summary>
/// <param name="model">The team model</param>
public void Create(Team model)
{
// Create a team
this.Repository.Create(model);
}
/// <summary>
/// Update a team
/// </summary>
/// <param name="model">The team model</param>
public void Update(Team model)
{
// Update a team
this.Repository.Update(model);
}
/// <summary>
/// Delete a team
/// </summary>
/// <param name="model">The team model</param>
public void Remove(Team model)
{
// Remove a team
this.Repository.Remove(model);
}
}
我知道这里有很多代码,但如果有人可以帮助我,我需要给你我的整个过程:) 所以,如果我在我的控制器中创建一个更新方法,如下所示:
private async Task<IHttpActionResult> Save(TeamBindingViewModel model)
{
// If our model is invalid, return the errors
if (!ModelState.IsValid)
return BadRequest(ModelState);
// Create a list of colours
var colours = new List<Colour>();
// For each colour in our model, add to our list
foreach (var colour in model.Colours)
colours.Add(new Colour()
{
Id = colour.Id,
Name = colour.Name,
Hex = colour.Hex
});
// If there is an id
if (model.Id > 0)
{
// Update our team
await this.Update(model, colours);
}
else
{
// Create our team
this.Create(model, colours);
}
// Save the database changes
await this.unitOfWork.SaveChangesAsync();
// Return Ok
return Ok(model);
}
private void Create(TeamBindingViewModel model, IList<Colour> colours)
{
// Create our new model
var team = new Team()
{
Id = model.Id,
Name = model.Name,
Sport = model.Sport
};
// Assign our colours to our team
team.Colours = colours;
// Otherwise, create a new team
this.service.Create(team);
}
private async Task Update(TeamBindingViewModel model, IList<Colour> colours)
{
// Create our new model
var team = new Team()
{
Id = model.Id,
Name = model.Name,
Sport = model.Sport
};
// Update the team
this.service.Update(team);
}
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;
}
更新将处理,一切正常。但是,如果我将更新方法更改为:
private async Task Update(TeamBindingViewModel model, IList<Colour> colours)
{
// Create our new model
var team = new Team()
{
Id = model.Id,
Name = model.Name,
Sport = model.Sport
};
// Get our current model
var current = await this.service.GetAsync(model.Id, "Colours");
var currentColours = current.Colours;
// Assign our original colours to our team
team.Colours = currentColours;
// Get our colours to remove and add
var coloursToRemove = GetDifference(currentColours, colours);
var coloursToAdd = GetDifference(colours, currentColours);
// 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);
}
我收到此错误:
“exceptionMessage”:“附加'Models.Team'类型的实体失败,因为同一类型的另一个实体已经具有相同的主键值。当使用'Attach'方法或设置状态时,可能会发生这种情况。如果图中的任何实体具有冲突的键值,则实体为“未更改”或“已修改”。这可能是因为某些实体是新的且尚未接收到数据库生成的键值。在这种情况下,使用“添加”方法或“添加”实体状态以跟踪图表,然后根据需要将非新实体的状态设置为“未更改”或“已修改”。“
我不确定为什么会出现此错误,但我认为它与尝试添加/删除查找表中的颜色有关。 任何人都可以为我提供这个问题的解决方案吗?
答案 0 :(得分:1)
你的出现是因为你正试图更新&#34; team&#34;当你有&#34;当前&#34;变量holdes在同一范围内的实体试试这个:
private async Task Update(TeamBindingViewModel model, IList<Colour> colours)
{
// Create our new model
//var team = new Team()
//{
// Id = model.Id,
// Name = model.Name,
// Sport = model.Sport
//};
// Get our current model
var current = await this.service.GetAsync(model.Id, "Colours");
current.Name = model.Name;
current.Sport = model.Sport;
var currentColours = current.Colours;
// Assign our original colours to our team
//team.Colours = currentColours;
// Get our colours to remove and add
var coloursToRemove = GetDifference(currentColours, colours);
var coloursToAdd = GetDifference(colours, currentColours);
// Loop through our colours to remove and remove them
if (coloursToRemove.Count > 0)
foreach (var colour in coloursToRemove)
current.Colours.Remove(colour);
// Loop through the colours to add and add them
if (coloursToAdd.Count > 0)
foreach (var colour in coloursToAdd)
current.Colours.Add(colour);
// Update the team
this.service.Update(current);
}