簡體   English   中英

SaveChanges 后如何從數據庫中更新緩存的 EF?

[英]How do you update cached EF from database after SaveChanges?

這是場景 - 不同的用戶通過從 web 頁面上的下拉列表中選擇一個值來進行更改。 下拉列表包含在 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));
}
}
}

在過去的兩天里,我已經多次搜索解決方案。 任何幫助表示贊賞。

實體框架 3.5 以令人難以置信的方式保存更改,但它已在 EF 4.0 中修復,我猜您使用的是 EF 3.5

Hover 您需要知道您的數據會發生什么以及 EF 如何保存數據。 您可以閱讀有關此問題的MSDN

現在您可以在 SaveChanges 時調用 refresh 方法來更新數據。

context.Refresh(RefreshMode.ClientWins, orders);

英孚 4.0 > 英孚 3.5

用戶 B 看不到用戶 A 所做的更改,因為用戶 B 的更改覆蓋了用戶 A 所做的更改。

您想要做的是在您的系統中實現並發檢查。 因此,當用戶 A 和用戶 B 在數據庫中獲取相同的 object 實例時,第一個進行更改並提交到數據庫的人將成功。 第二個人所做的更改將因並發異常而失敗 - 因為您的后端系統將檢測到用戶 B 對已被先前更改修改的“陳舊”實體進行了更改。

由於您使用的是 EF,因此您很幸運,因為它有一個很好的系統可以為您管理並發。 在您的實體中選擇一個屬性以用於並發檢查 - 通常它是 object 的“最后修改日期”。

打開 EDMX 文件,單擊您希望用於並發檢查的所需屬性(例如 LastDateModified),然后設置 ConcurrencyMode=Fixed。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM