C# 创建通用存储库InsertOrUpdate函数(错误)

C# 创建通用存储库InsertOrUpdate函数(错误),c#,entity-framework,generics,C#,Entity Framework,Generics,我正在尝试在我的通用存储库的抽象层上创建InsertOrUpdate函数,由我的具体对象存储库继承: 这是我的代码: public abstract class GenericRepository<T> : IGenericRepository<T> where T : class { private readonly OhmioEntities context = new OhmioEntities(); public IQueryable<

我正在尝试在我的通用存储库的抽象层上创建InsertOrUpdate函数,由我的具体对象存储库继承:

这是我的代码:

 public abstract class GenericRepository<T> : IGenericRepository<T> where T : class
 {
    private readonly OhmioEntities context = new OhmioEntities();

    public IQueryable<T> FindBy(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
    {
        IQueryable<T> query = context.CreateObjectSet<T>().Where(predicate);
        return query;
    }

    public void InsertOrUpdate(T entity, System.Linq.Expressions.Expression<Func<T, bool>> Findpredicate)
    {   
        T _dbRecord = this.FindBy(Findpredicate).FirstOrDefault();
        if (_dbRecord != null)
        {
            // Edit the record
            _dbRecord = entity;
            context.ObjectStateManager.ChangeObjectState(entity, System.Data.EntityState.Modified);
        }
        else
        {
            // Agrego el registro
            context.CreateObjectSet<T>().AddObject(entity);
        }

        // Save Changes to DB
        context.SaveChanges();
    }
} 
也就是说:

{“ObjectStateManager不包含引用“DataLayer.Clients”类型的对象的ObjectStateEntry.”

为什么我会得到这个?有什么线索吗?谢谢

UDATE

好吧,我让它工作了,只是需要更多的代码:

public void InsertOrUpdate(T entity, System.Linq.Expressions.Expression<Func<T, bool>> Findpredicate)
    {   
        T _dbRecord = this.FindBy(Findpredicate).FirstOrDefault();
        if (_dbRecord != null)
        {
            // Edit the object
            context.ObjectStateManager.ChangeObjectState(_dbRecord, System.Data.EntityState.Modified);
            context.Detach(_dbRecord);
            _dbRecord = entity;
            context.AttachTo(entity.ToString().Split('.')[2], _dbRecord);
            context.ObjectStateManager.ChangeObjectState(_dbRecord, System.Data.EntityState.Modified);                                
        }
        else
        {
            // add the object
            context.CreateObjectSet<T>().AddObject(entity);
        }

        // Save Changes to DB
        context.SaveChanges();
    }
public void InsertOrUpdate(T实体,System.Linq.Expressions.Expression Findpredicate)
{   
T_dbRecord=this.FindBy(Findpredicate).FirstOrDefault();
if(_dbRecord!=null)
{
//编辑对象
context.ObjectStateManager.ChangeObjectState(_dbRecord,System.Data.EntityState.Modified);
context.Detach(_dbRecord);
_dbRecord=实体;
context.AttachTo(entity.ToString().Split('.')[2],_dbRecord);
context.ObjectStateManager.ChangeObjectState(_dbRecord,System.Data.EntityState.Modified);
}
其他的
{
//添加对象
context.CreateObjectSet().AddObject(实体);
}
//将更改保存到数据库
SaveChanges();
}

您已经创建了一个新的
客户端
对象,但我想还没有添加到上下文中。首先尝试在上下文中添加,然后将其状态更改为
Modified

另外,您的
FindBy
函数正被用作信号,也许您可以使用
任何
函数,而不是在该函数中实际加载实体,并将返回类型更改为
布尔


还有一件事,您的类的示例用法有点奇怪。我不确定我们是否可以像您正在调用的那样直接调用类中的方法,而不必在其他方法中使用此方法。

更新中的加载和分离技巧是不必要的。您只需在不加载实体的情况下询问数据库实体是否已存在(使用
Any()
而不是
FirstOrDefault()
):


请注意,这两种解决方案仅用于更新实体的标量属性。它不适用于更改的关系和导航属性。没有简单的通用解决方案可用于此具有任意对象图的更通用更新方案。

谢谢您的回答。是的,您提到的问题是我需要附加已编辑的对象。问题是,如果附加已编辑的对象,则对象已存在错误。最后我找到了解决方案,请看我的更新。关于第二点,FindBy不仅仅用作信号:如果对象存在,我需要一个对该对象的引用。我不明白第3点,你能更具体一点吗?@ericpap我的最后一点实际上是关于你的具体类
ClientsRepository
,在这个类中,你直接调用
this.InsertOrUpdate
方法,而不使用某种方法中的这一行。谢谢!好消息!唯一不清楚的是最后一段。你说我不能更新关系和导航是什么意思?如果我的客户机有一个与EF上的其他表相关的PK字段,它不会改变吗?再次感谢@ericpap:例如:如果您的
客户端
实体有一个外键属性
AddressID
地址
实体,并且您将该
AddressID
2
更改为
3
,那么更新将起作用,因为
AddressID
是一个标量属性。如果更改导航属性
Client.Address
,它将不起作用。更困难的情况是,如果您有一个集合,例如
Client.Orders
,您从该集合中删除订单,在该集合中添加新订单或更改订单。不会使用上述简单方法将其更新到DB。更不用说更复杂的事情了,比如孙辈们……我试过你的代码,工作得完美无缺!我尝试了一些类似的东西,但它给我的附加错误。现在我工作得很好。非常感谢。
context.ObjectStateManager.ChangeObjectState(entity, System.Data.EntityState.Modified);
public void InsertOrUpdate(T entity, System.Linq.Expressions.Expression<Func<T, bool>> Findpredicate)
    {   
        T _dbRecord = this.FindBy(Findpredicate).FirstOrDefault();
        if (_dbRecord != null)
        {
            // Edit the object
            context.ObjectStateManager.ChangeObjectState(_dbRecord, System.Data.EntityState.Modified);
            context.Detach(_dbRecord);
            _dbRecord = entity;
            context.AttachTo(entity.ToString().Split('.')[2], _dbRecord);
            context.ObjectStateManager.ChangeObjectState(_dbRecord, System.Data.EntityState.Modified);                                
        }
        else
        {
            // add the object
            context.CreateObjectSet<T>().AddObject(entity);
        }

        // Save Changes to DB
        context.SaveChanges();
    }
public void InsertOrUpdate(T entity, Expression<Func<T, bool>> Findpredicate)
{   
    bool exists = this.FindBy(Findpredicate).Any();
    if (exists)
    {
        context.CreateObjectSet<T>().Attach(entity);
        context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);
    }
    else
    {
        context.CreateObjectSet<T>().AddObject(entity);
    }

    context.SaveChanges();
}
public void InsertOrUpdate(T entity, Expression<Func<T, bool>> Findpredicate)
{   
    T _dbRecord = this.FindBy(Findpredicate).FirstOrDefault();
    if (_dbRecord != null)
    {
        context.CreateObjectSet<T>().ApplyCurrentValues(entity);
    }
    else
    {
        context.CreateObjectSet<T>().AddObject(entity);
    }

    context.SaveChanges();
}