【问题标题】:How do you update cached EF from database after SaveChanges?SaveChanges 后如何从数据库中更新缓存的 EF?
【发布时间】:2011-05-03 14:53:58
【问题描述】:

这是场景 - 不同的用户通过从网页上的下拉列表中选择一个值来进行更改。下拉列表包含在 DataView 中或通过构建表。如果用户 A 对第 1 行进行了更改,它将更新数据库并在重新绑定后显示其更改。随后,当用户 A 进行更改并对第 2 行进行更改时,用户 B 在同一页面上。更新数据库并重新绑定 gridview(或重建表)。但是,用户 B 没有看到用户 A 所做的更改。我假设这是由于 EF 缓存造成的。如果用户刷新页面(或被重定向回页面),他们可以看到数据库中的最新数据。

如何在不刷新页面的情况下从数据库中获取最新数据?

每次在PageLoad中都会调用绑定的方法,包括回发:

    private void PopulateFormForDealer(DateTime BeginDate, DateTime EndDate, int DealerID, bool UnVerifiedOnly)
    {
        try
        {                
        using (var DB = new NIMSModel.NIMSEntities())
        {

    var scheduledOrders = from r in DB.Reservations
              join o in DB.Orders on r.ResID equals o.ReservationID
              where r.ResDate <= EndDate && r.ResDate >= BeginDate && r.Claimed == "Y"
              && r.DealerID == DealerID //&& r.Verified == VerifiedOnly
              orderby r.ResDate, r.ResID
              select new { r.ResID, o.ID, o.VantiveOrderID, o.CustomerFirstName, o.CustomerCity, o.CustomerState, o.CustomerZipCode, o.OrderType.Type, r.ResDate, r.TimeOfDay, r.Source, DealerInstallerID = r.DealerInstallerID == null ? 0 : r.DealerInstallerID, r.Verified, r.Notes };


    GridView1.DataSource = scheduledOrders.ToList();
    GridView1.DataBind();

}
}
catch (Exception ex)
{
LogError(ex);
}

}

这是下拉列表的事件处理程序:

    protected void ddInstaller_SelectedIndexChanged(Object sender, EventArgs e)
    {
        try
        {
string foo = ((DropDownList)sender).SelectedValue;
Guid theg = new Guid(((DropDownList)sender).SelectedValue.Split('_')[1].ToString());
int? installerid = int.Parse(((DropDownList)sender).SelectedValue.Split('_')[0].ToString());
string installername = ((DropDownList)sender).SelectedItem.Text;

if (installerid == 0)
{
    installerid = null;
}

int testvalidguidlen = theg.ToString().Replace("0", "").Length;
if (testvalidguidlen > 10)
{
    string note;
    using (var DB = new NIMSModel.NIMSEntities())
    {
    var reservatoins = DB.Reservations.Where(r => r.ResID == theg).FirstOrDefault();

    if (reservatoins.DealerInstallerID != installerid)
    {
        var orders = DB.Orders.Where(o => o.ReservationID == theg).FirstOrDefault();

        reservatoins.DealerInstallerID = installerid;
        orders.InstallerID = installerid;

        if (reservatoins.Notes == null || reservatoins.Notes.Length >= 1800)
        {
        note = "[" + DateTime.Now.ToString("yyyy.MM.dd hh:mm:ss") + "] TechChange by: " + PTNAccount.UserName + "(" + PTNAccount.LoginID + "); NewTech: " + installername + ";";
        }
        else
        {
        note = reservatoins.Notes + "[" + DateTime.Now.ToString("yyyy.MM.dd hh:mm:ss") + "] TechChange by: " + PTNAccount.UserName + "(" + PTNAccount.LoginID + "); NewTech: " + installername + ";";
        }
        reservatoins.Notes = note;

        DB.SaveChanges();
    }
    }
}
}
catch (Exception ex)
{
LogError(ex);
}

}

这里是构建下拉列表的方法:

    private DropDownList PopulateInstallerDropDownList(DropDownList ddl, String resID)
    {

try
{
using (var DB = new NIMSModel.NIMSEntities())
{
    var DealerInstallers = from di in DB.DealerInstallers
               where di.Active == 1 && di.IsDeleted == "N" && di.DealerID == DealerID
               orderby di.Name
               select new { di.ID, di.Name };
    var DealerInstallersArray = DealerInstallers.ToArray();
    ListItem li = new ListItem("","0_" + resID);
    ddl.Items.Add(li);

    foreach (var installer in DealerInstallersArray)
    {
    ddl.Items.Add(new ListItem(installer.Name.ToString(), (installer.ID.ToString() + (string)"_" + resID.ToString())));
    }
}
}
catch (Exception ex)
{
string foo = ex.Message;
}
return ddl;

}

这里是 RowDataBound 事件处理程序:

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{

if (e.Row.RowType == DataControlRowType.DataRow)
{
string reservationID = DataBinder.Eval(e.Row.DataItem, "ResID").ToString();
DropDownList ddl = (DropDownList)e.Row.FindControl("ddInstaller");
PopulateInstallerDropDownList(ddl, reservationID);
string dealerInstallerId = DataBinder.Eval(e.Row.DataItem, "DealerInstallerID").ToString();

if (dealerInstallerId != "0")
{
    dealerInstallerId = dealerInstallerId + "_" + reservationID;
}

if (dealerInstallerId.Length > 1)
{
    ddl.SelectedIndex = ddl.Items.IndexOf(ddl.Items.FindByValue(dealerInstallerId));
}
}
}

在过去的两天里,我已经多次搜索解决方案。任何帮助表示赞赏。

【问题讨论】:

  • 我很确定这与 EF 缓存完全无关,默认情况下没有数据缓存,除非您使用自定义缓存提供程序。
  • 数据多久更改一次,用户现在拥有最新信息有多重要?最简单的解决方案是计时器上的更新面板。但这对你来说就足够了吗?
  • 您是否 100% 确定要在回发中调用绑定方法?由于 ToList() 将始终调用查询,并且 BrokenGlass 提到没有默认数据缓存。
  • @hyp 除非我读错了,否则他希望当我点击提交按钮时他也想更新你的页面。
  • 我明白,当我点击提交时,其他人所做的更改不会出现....?混乱

标签: c# asp.net entity-framework linq-to-entities


【解决方案1】:

Entity framework 3.5 以令人难以置信的方式保存更改,但在 EF 4.0 中已修复 我猜你使用的是 EF 3.5

将鼠标悬停在您需要了解您的数据发生了什么情况以及 EF 如何保存数据。你可以阅读MSDN 来了解这个问题。

现在你可以在 SaveChanges 时调用 refresh 方法来更新数据。

context.Refresh(RefreshMode.ClientWins, orders);

EF 4.0 > EF 3.5

【讨论】:

    【解决方案2】:

    用户 B 看不到用户 A 所做的更改,因为用户 B 的更改覆盖了用户 A 所做的更改。

    您想要做的是在您的系统中实现并发检查。因此,当用户 A 和用户 B 在数据库中获取相同的对象实例时,第一个进行更改并提交到数据库的人将成功。第二个人所做的更改将因并发异常而失败 - 因为您的后端系统将检测到用户 B 对已被先前更改修改的“陈旧”实体进行了更改。

    既然您使用的是 EF,那么您很幸运,因为它有一个很好的系统可以为您管理并发。在您的实体中选择一个属性以用于并发检查 - 通常是对象的“上次修改日期”。

    打开 EDMX 文件,单击您希望用于并发检查的所需属性(例如 LastDateModified),然后设置 ConcurrencyMode=Fixed。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-26
      • 1970-01-01
      • 1970-01-01
      • 2019-09-01
      • 1970-01-01
      • 2021-08-26
      • 2017-02-13
      • 1970-01-01
      相关资源
      最近更新 更多