Entity Framework 6 查询时上下文重复

Posted

技术标签:

【中文标题】Entity Framework 6 查询时上下文重复【英文标题】:Entity Framework 6 Context duplicate while query 【发布时间】:2015-05-27 09:21:23 【问题描述】:

我有一些我无法解决的问题。在我的项目中,我首先使用 EF6 Code。我创建了一些模型,但它们的头部是用户模型:

 public class User

    [Required]
    public Guid Id  get; set; 
    [Required, MaxLength(20), MinLength(5), UniqProp] 
    public string Login  get; set; 
    [Required, MaxLength(20), MinLength(8)]
    public string Password  get; set; 
    [Required]
    public Role Role  get; set; 
    [Required]
    public string FirstName  get; set; 
    [Required]
    public string LastName  get; set; 
    [Required, UniqProp]
    public string Email  get; set; 
    [Required]
    public string City  get; set; 
    public virtual List<Ticket> Tickets  get; set;  

我还创建了自己的上下文,如下所示:

public class TheatreContext : DbContext

    public DbSet<User> Users  get; set; 
    public DbSet<Role> Roles  get; set; 
    public DbSet<Ticket> Tickets  get; set; 
    public DbSet<Play> Plays  get; set; 

在此之后,我以这种方式初始化我的数据库:

 using (var db = new TheatreContext())
 
      Adding objects to db and save changes.
 

那时一切正常。所有数据都添加到数据库中。然后我决定创建我的Repository 类来使用 db 进行一些操作:

public class TheatreRepository<T> : IRepository<T> where T: class

    private readonly TheatreContext _context;
    private readonly DbSet<T> _dbSet;

    public TheatreRepository()
    
        _context = new TheatreContext();
        _dbSet = _context.Set<T>();
    

    public void Add(T entity)
     
        _dbSet.Add(entity);
    

    public DbSet<T> GetAll()
    
        return this._dbSet;
    

    public void Commit()
     
        _context.SaveChanges();
    

当我尝试以这种方式添加新用户时:

var repo = new TheatreRepository<User>();
var roleRepo = new TheatreRepository<Role>();

var newUser = new User
                  
                      Id = Guid.NewGuid(),
                      Login = "Lionqweq",
                      City = "Minsk",
                      Role = roleRepo.GetAll().First(role => role.RoleType == RoleType.User),
                      FirstName = "Alex",
                      Email = "AlexDanger@gmail.com",
                      Password = "dsas1qsqda",
                      LastName = "Ivanov"
                  ;
repo.Add(newUser);
repo.Commit();

在调用Commit(数据库中的SaveChanges)时,它会抛出DbUpdateException,因为我尝试使用现有ID 添加到Role 表对象。这对我来说没有意义!实际上我没有添加任何角色,我尝试仅添加User

我的Role 表在本地包含的内容:

我在本地的Users 表中拥有的内容:

请有任何建议和想法!我很困惑

【问题讨论】:

【参考方案1】:

你应该尝试而不是

[Required]
public Role Role  get; set; 

要使用也使用对 FK 的引用:

[Required]
public Guid RoleId  get; set; 
public virtual Role Role  get; set;  

当你创建一个新用户时,只设置 RoleId

这是一个例子: EF first code

【讨论】:

亲爱的丹妮,谢谢!你对我帮助很大!我以这种方式解决了它: public Guid RoleId get;放; [ForeignKey("RoleId")] public virtual Role Role get;放; 【参考方案2】:

你的问题来了

public TheatreRepository()

    _context = new TheatreContext();
    _dbSet = _context.Set<T>();

如果您正在实现存储库模式,那么您的存储库类必须在构造函数中获取上下文,即 DI,所以它必须是这样的

public TheatreRepository(TheatreContext context)

    _context = context;
    _dbSet = _context.Set<T>();
 

解释:

存储库必须使用相同的上下文来跟踪发生的更改和加载的(本地)实体,因此请考虑在存储库之前声明您的上下文,如下所示:

var db = new TheatreContext();
var repo = new TheatreRepository<User>(db);
var roleRepo = new TheatreRepository<Role>(db);
var newUser = new User

    Id = Guid.NewGuid(),
    Login = "Lionqweq",
    City = "Minsk",
    Role = roleRepo.GetAll().First(role => role.RoleType == RoleType.User),
    FirstName = "Alex",
    Email = "AlexDanger@gmail.com",
    Password = "dsas1qsqda",
    LastName = "Ivanov"
;
repo.Add(newUser);
repo.Commit();

【讨论】:

你是说他们都应该使用相同的 TheatreContext 实例吗? (“必须注入依赖项”并不完全暗示) 所以这意味着我只能为所有存储库创建一个上下文?如果我是对的,这意味着对于每个表,我也会将我的数据存储在本地,并且我会占用大量资源

以上是关于Entity Framework 6 查询时上下文重复的主要内容,如果未能解决你的问题,请参考以下文章

Entity Framework 6 - . 创建新对象,保存更改,根据新 id 重新查询对象,返回 null

Entity Framework Core - 在尝试运行第二个查询时释放

Entity Framework 4 和查询结果的缓存

为啥要使用 Attach 来更新 Entity Framework 6?

MVC 脚手架不支持 Entity Framework 6 或更高版本

Entity Framework linq 中的动态表名