EF和MVC - 共同合作的方法

时间:2015-04-13 21:45:21

标签: c# asp.net-mvc entity-framework async-await

我长时间使用以下方法(约5年):

在控制器中初始化XXXEntities创建一个大类,并使用DB为每个操作创建每个方法。例如:

public class DBRepository
{
    private MyEntities _dbContext;
    public DBRepository()
    {
        _dbContext = new MyEntities();
    }

    public NewsItem NewsItem(int ID)
    {
        var q = from i in _dbContext.News where i.ID == ID select new NewsItem() { ID = i.ID, FullText = i.FullText, Time = i.Time, Topic = i.Topic };
        return q.FirstOrDefault();
    }

    public List<Screenshot> LastPublicScreenshots()
    {
        var q = from i in _dbContext.Screenshots where i.isPublic == true && i.ScreenshotStatus.Status == ScreenshotStatusKeys.LIVE orderby i.dateTimeServer descending select i;
        return q.Take(5).ToList();
    }

    public void SetPublicScreenshot(string filename, bool val)
    {
        var screenshot = Get<Screenshot>(p => p.filename == filename);
        if (screenshot != null)
        {
            screenshot.isPublic = val;
            _dbContext.SaveChanges();
        }

    }

    public void SomeMethod()
    {
            SomeEntity1 s1 = new SomeEntity1() { field1="fff", field2="aaa" };
            _dbContext.SomeEntity1.Add(s1);
            SomeEntity2 s2 = new SomeEntity2() { SE1 = s1 };
            _dbContext.SomeEntity1.Add(s2);
            _dbContext.SaveChanges();
    }

一些外部代码创建DBRepository对象和调用方法。 它工作正常。但现在异步操作进来了。所以,如果我使用像

这样的代码
    public async void AddStatSimplePageAsync(string IPAddress, string login, string txt)
    {
        DateTime dateAdded2MinsAgo = DateTime.Now.AddMinutes(-2);
        if ((from i in _dbContext.StatSimplePages where i.page == txt && i.dateAdded > dateAdded2MinsAgo select i).Count() == 0)
        {
            StatSimplePage item = new StatSimplePage() { IPAddress = IPAddress, login = login, page = txt, dateAdded = DateTime.Now };
            _dbContext.StatSimplePages.Add(item);
            await _dbContext.SaveChangesAsync();
        }
    }

可能是这样一种情况,当下一个代码将在SaveChanged完成之前执行,另外一个实体将被添加到_dbContext,在某些操作之前不应保存。例如,一些代码:

                DBRepository _rep = new DBRepository();
                _rep.AddStatSimplePageAsync("A", "b", "c");
                _rep.SomeMethod();

我担心,SaveChanged将在行

之后调用
        _dbContext.SomeEntity1.Add(s1);

但之前

        _dbContext.SomeEntity2.Add(s2);

(即这两个动作是原子操作)

我是对的吗?我的方法现在错了吗?应该采用哪种方法?

PS。据我了解,将是以下堆栈:

1. calling AddStatSimplePageAsync
2. start calling await _dbContext.SaveChangesAsync(); inside AddStatSimplePageAsync
3. start calling SomeMethod(), _dbContext.SaveChangesAsync() in AddStatSimplePageAsync is executing in another (child) thread.
4. complete _dbContext.SaveChangesAsync() in child thread. Main thread is executing something in SomeMethod()

1 个答案:

答案 0 :(得分:2)

好的这次我(想)已经解决了你的问题。

首先,您对SaveChanges方法进行了两次单独调用,这很奇怪。通常你应该在所有操作结束时尝试使用它然后处理它。

即使是的,你的担忧是对的,但这里需要澄清一些。

  1. 遇到asyncawait时,不考虑线程,而是考虑任务,two different concepts

  2. 读一下这篇伟大的article。有一个图像可以解释你的一切。

  3. 简单地说,如果您不等待异步方法,您可能会面临后续操作可能会损害&#34;执行第一个。要解决它,只需等待它。