如何使用EF插入/更新行?

时间:2011-06-20 16:26:23

标签: asp.net-mvc-3 entity-framework-4 insert-update

使用Entity Framework插入/更新行的正确方法是什么?

我知道这三种方法:

1 - 使用Attach

var newSale = _context.ST_Sales.FirstOrDefault(x => x.SaleId == saleId);
newSale.Hours = 2;
_context.ST_Sales.Attach(newSale);
_context.ObjectStateManager.ChangeObjectState(newSale, EntityState.Modified);
_context.SaveChanges();

2 - 使用ApplyCurrentValues

var newSale = _context.ST_Sales.FirstOrDefault(x => x.SaleId == saleId);
newSale.Hours = 2;
_context.ST_Sales.ApplyCurrentValues(newSale);
_context.SaveChanges();

3 - 使用EF logic

var newSale = _context.ST_Sales.FirstOrDefault(x => x.SaleId == saleId);
newSale.Hours = 2;
_context.SaveChanges(); // EF tracks the newSale obj and knows that was changed

要插入,还有一种方法可以使用AddObject

var newSale = new ST_Sales();
newSale.Hours = 2;
_context.ST_Sales.AddObject(newSale);
_context.SaveChanges();

我遇到的问题是EF上的一个错误,说修改后的行仍在内存中。

我的方案:

  • 20位用户可以向自己的公司增加销售额。

我有一个简单的表关系:

tbl_Companies { CompanyId, Name }
tbl_Sales     { CompanyId, Hours, Amount }

我的Edit View简单获取本周的sales collection

var model = _context.ST_Sales.Where(x => x.CompanyId == 2);
return View(model);

并在HttpPost操作上,我只需遍历每个操作并保存数据库更改,如

[HttpPost]
public ViewResult Index(List<ST_Sales> model)

bool newSale = false;
foreach( var s in model ) { // let's loop through all

    newSale = false;

    var sale = _context.ST_Sales.FirstOrDefault(x => x.SaleId == s.SaleId);
    if( sale == null) {

        // sale was not found, let's add it (this happens for todays date
        //    as there is no info yet in the db, but we need to add today's info)

        sale = new ST_Sale();
        sale.Company.Id = currentLoggedInUser.companyId;

        newSale = true;  // let's say it's a new sale so we can add the new object to the changes to commit
    }

    sale.Hours = s.Hours;
    sale.Amount = s.Amount;

    if( newSale ) {
        // it's a new sale, let's add the obj to our Entity
        _context.ST_Sales.AddObject(sale);
    } 
    else {
        // no need to do anything, EF is tracking the changes of existing objects
    }
}

_context.SaveChanges();

这适用于一个用户...但如果我注销并使用其他用户登录,并且我可以在断点中看到companyId值不同,很快我就会提交更改以保存我得到奇怪的错误:

  

IEntityChangeTracker的多个实例无法引用实体对象。

我做错了什么?


我正在Controller级别创建一个新实例,如:

public class SalesController : Controller
{
    private SalesTrackerRepository db = SalesTrackerRepository.Instance;

    ...
}

并使用Sams Code

中的来源

此外,我使用了Rick Strahl代码并最终使用:

public class SalesController : Controller
{
    private SalesTrackerRepository db = 
            SalesTrackerRepositoryFactory.GetWebRequestScopedDataContext<SalesTrackerRepository>();

    ....

}

我一直得到同样的错误:(


我的测试基于Chrome和Opera使用不同凭据的同一台计算机。

  

如何在此类测试中出现此错误?

3 个答案:

答案 0 :(得分:0)

应为每个请求创建并释放_context不再。多个并发请求不应共享上下文。

答案 1 :(得分:0)

我会尝试使用此帖子中的IDatabaseFactory:Entity Framework 4 CTP 4 / CTP 5 Generic Repository Pattern and Unit Testable以及IoC容器(Structuremap,Unity,Ninject)来根据Http请求确定DatabaseFactory实例化的范围。

代码应如下所示:

IDatabaseFactory.cs

public interface IDatabaseFactory : IDisposable
    {
        Database Get();
    }

DatabaseFactory.cs

public class DatabaseFactory : Disposable, IDatabaseFactory {
        private Database _database;
        public Database Get() {
            return _database ?? (_database = new Database());
        }
        protected override void DisposeCore() {
            if (_database != null)
                _database.Dispose();
        }
    }

一次性扩展方法:

<强> Disposable.cs

public class Disposable : IDisposable
    {
        private bool isDisposed;

        ~Disposable()
        {
            Dispose(false);
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        private void Dispose(bool disposing)
        {
            if(!isDisposed && disposing)
            {
                DisposeCore();
            }

            isDisposed = true;
        }

        protected virtual void DisposeCore()
        {
        }
    }

答案 2 :(得分:0)

得到了错误!

我正在使用MemoryCache来缓存一些结果,并意识到我正在使用该缓存来请求EntityKey

我的建议:请检查您的项目中是否真的要处理所有这些变通办法!