【问题标题】:EF and MVC - approach to work togetherEF 和 MVC - 协同工作的方法
【发布时间】:2015-04-14 13:11:17
【问题描述】:

我长期使用以下方法(大约 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()

【问题讨论】:

  • 我不确定我是否收到了您的问题。看起来您担心异步操作,如果在另一个请求到来时未完成,可能会给您的代码分配带来一些问题?你能详细说明一下吗?
  • 向主要问题添加了详细信息
  • 这不是异步/等待操作的工作方式。 Async/await 不会转到另一个需要 awaited 函数调用结果的函数。您当前的方法对我来说似乎很好,要进一步阅读,请查看 MSDN,特别是我在这里链接到的部分 - msdn.microsoft.com/en-us/library/…
  • 另外,您的示例编辑,您并没有等待您的AdStatSimplePageAsync 方法,因此,它将正常运行(同步)。
  • 据我了解,方法 AddStatSimplePageAsync 在等待 _dbContext.SaveChangesAsync();正在调用,但在完成之前。看我问题的最后,我补充了一些东西

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


【解决方案1】:

好吧,这次我(认为)遇到了你的问题。

起初,您有两次单独调用SaveChangesmethod,这很奇怪。通常,您应该尝试在所有操作结束时拥有它,然后将其丢弃。

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

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

  2. 阅读这个伟大的article。有一张图片几乎可以解释一切。

简而言之,如果您不等待异步方法,您可能会面临后续操作可能“损害”第一个操作的执行的风险。要解决它,只需等待它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-19
    • 2019-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多