我有以下实体数据模型,为简洁而简化;
public abstract class Entity<T> : BaseEntity, IEntity<T>
{
[Key]
public virtual T Id { get; set; }
}
public class User : Entity<int>
{
public List<Category> Categories { get; set; }
}
public class Category : Entity<int>
{
public string Description { get; set; }
}
public class List : Entity<int>
{
public Category Category { get; set; }
}
可以使用DbContext从DbContext访问这些内容,这些DbContext由通用服务或更自定义的实现公开,以提供业务逻辑。
当我发布数据库并将以下代码添加到Seed()方法时,一切都很好,数据直接在数据库中看起来很好。
var user = new User
{
Email = "",
Categories = new List<Category>
{
new Category
{
Description = "Category 1",
},
new Category
{
Description = "Category 2",
}
}
};
context.Users.AddOrUpdate(u => u.Email, user);
var list = new List()
{
Id = 1,
Description = "Test List",
UserId = 1,
Category = user.Categories.FirstOrDefault()
};
context.Lists.AddOrUpdate(u =>u.Id, list);
请注意,用户拥有类别,您可以(应该只能)通过访问Categories属性来创建它们。
这给了我;
我在控制器中使用这些对象;
public ActionResult Edit(int id)
{
var categories = _usersService.GetUser(User.Id).Categories;
categories.Insert(0, new Category {Description = "", Id = 0});
var list = _listsService.GetList(id);
var viewModel = new EditViewModel
{
Id = list.Id,
Reference = list.Reference,
Description = list.Description,
CategoryId = list.Category?.Id ?? 0,
Categories = new SelectList(categories.AsEnumerable(), "Id", "Description")
};
return View(viewModel);
}
在上面的测试中,我使用种子期间插入的List
,我可以看到List
确实有Category
,且值正确。
有关信息,我使用的是以下ViewModel。我一直在调查方法,以便能够选择&#39;来自DropDown的User.Categories
,这似乎目前效果最佳。
public class EditViewModel
{
[Required]
public int Id { get; set; }
[Required]
public string Description { get; set; }
public IEnumerable<SelectListItem> Categories { get; set; }
[ScaffoldColumn(false)]
public int CategoryId { get; set; }
[ScaffoldColumn(false)]
public Guid Reference { get; set; }
}
填充的ViewModel看起来像这样;
[HttpPost]
public ActionResult Edit(EditViewModel model)
{
if (ModelState.IsValid)
{
var categories = _usersService.GetUser(User.Id).Categories;
var list = _listsService.GetList(model.Id);
list.Description = model.Description;
list.Category = categories.FirstOrDefault(x => x.Id == model.CategoryId);
_listsService.Update(list);
categories.Insert(0, new Category { Description = "", Id = 0 });
model.Categories = new SelectList(categories.AsEnumerable(), "Id", "Description");
return View(model);
}
return View(model);
}
因此,在以下场景中,会发生这种情况。为清楚起见,每次我这样做,我都会回到列表索引并再次获得编辑;
用于更新List的代码是;
public void Update(T entity)
{
if (entity == null) throw new ArgumentNullException(nameof(entity));
_context.Entry(entity).State = EntityState.Modified;
_context.SaveChanges();
}
现在,我知道这是我正在做的事情,但对EF来说是新手,我不知道。
答案 0 :(得分:1)
问题在于如何设定价值。
我需要设置外键并为此值赋值。
public class List : Entity<int>
{
public int CategoryId { get; set; }
[ForeignKey("CategoryId")
public Category Category { get; set; }
}
然后将值设置为
var list = _listsService.GetList(model.Id);
list.Description = model.Description;
list.CategoryId = model.CategoryId;
list.Category = null;
_listsService.Update(list);
在此之后,从存储库中获取列表时,将正确填充Category和CategoryID。
问题在于将实体设置为已修改,这内部表明该类别为“新”,而实际上并非如此。你也可以'附加'和现有的类别到实体/上下文,但决定上面的方法更好。
稍微好一点的方法是创建一个新的'UpdateList'方法,可以调用它而不是通用更新。此方法将在控制器方法之外执行相关属性的设置。
答案 1 :(得分:0)
问题可以在视野中,你没有我将EF添加新记录而不是更新现有记录。
答案 2 :(得分:0)
一般情况下:在为自定义类命名时(例如List
),请注意现有的类:
public class List : Entity<int>
{
public Category Category { get; set; }
}
请注意,您在正确的命名空间中使用了正确的类。
var user = new User
{
Email = "",
Categories = new YourOwnNamespace.List<Category>
{
new Category
{
Description = "Category 1",
},
new Category
{
Description = "Category 2",
}
}
};
避免将类和属性命名为现有名称。在例如,更改List
课程'MYLIST'。强>
答案 3 :(得分:-1)
我不确定,但您可以编写更新方法,如下所示:
public void Update(T entity)
{
if (entity == null) throw new ArgumentNullException(nameof(entity));
var item = _collection.Find(item.Id);
if (item == null) throw new ArgumentNullException(nameof(item ));
_context.Entry(item).CurrentValues.SetValues(entity);
_context.SaveChanges();
}