2013-09-26 67 views
0

我是新開發人員,嘗試使用Entity Framework 5.0(數據庫優先方法)檢索記錄以在ASP.NET Web應用程序頁面上的FormView中進行顯示和編輯,但我不確定最好的解決方法。在Web應用程序中使用實體框架檢索和更新記錄

檢索記錄,我用下面的代碼:

protected void Page_Load(object sender, EventArgs e) 
{ 
    LoadData(int.Parse(Session["PersonID"].ToString())); 
} 

private void LoadData(int iPersonID) 
{ 
    using (PeopleEntities ctx = new PeopleEntities()) 
    { 
     var query = (from a in ctx.People 
        where a.PersonID == iPersonID 
        select a).FirstOrDefault(); 

     TextBoxFirstName.Text = query.FirstName; 
     TextBoxLastName.Text = query.LastName; 
    } 
} 

,並保存它,我用:

protected void ButtonSave_Click(object sender, EventArgs e) 
{ 
    SaveEmployee(int.Parse(Session["PersonID"].ToString())); 
} 

private void SaveEmployee(int iPersonID = 0) 
{ 
    using (PeopleEntities ctx = new PeopleEntities()) 
    { 
     var query = (from a in ctx.People 
        where a.PersonID == iPersonID 
        select a).FirstOrDefault(); 

     query.FirstName = TextBoxFirstName.Text; 
     query.LastName = TextBoxLastName.Text; 
     ctx.SaveChanges(); 
    } 
} 

看來愚蠢我有這兩種方法各自查詢數據庫來檢索和更新記錄,但是,我又是一個新手,也許我只是想念一些東西。有沒有一種方法來填充與實體的FormView上的控件,並有一個方法來保存記錄,而不必手動分配基於狀態的值(query.FirstName = TextBoxFirstName.Text等)?

我已經看到了EntityDataSource,但我不認爲這將是一個很好的選擇,除了最簡單的東西。

任何人都可以告訴我,我所做的事情是好的還是提供更好的示例或指導?

非常感謝您的幫助!

回答

0

這也是我的做法。有必要檢索你想更新的對象。

1

最好的辦法,恕我直言,是當你只檢索到DISPLAY的數據,沒有改變跟蹤。這將避免性能問題。因此,請使用AsNoTracking方法來避免更改跟蹤代理。

對於更新,您應該加載WITH啓用change-tracking,這就是爲什麼在保存部分沒有調用AsNoTracking

記得檢查空值。您正在使用FirstOrDefault,但由於您使用的是主鍵,因此不會有第二條記錄,因此只使用SingleOrDefault。但由於可能會發生默認值(空),請檢查空值。

另外,使用lambda表達式。起初他們並不是那麼容易,但是你可以用一點點努力,他們會簡化你的代碼。

但是從您的問題,有一些解決方法來避免這種情況,但它們不是最好的方法。您應該避免使用長時間生活的實體,並將長期生活對象的ViewModel設爲首選,將UnitOfWork模式記在存儲庫和持久實體中。

如果你真的想要,你可以從上下文Detach你的實體,在任何地方使用它,當你準備好,Attach回來,並設置它的狀態Modified。 對於這一點,看看這裏:http://msdn.microsoft.com/en-us/library/bb896271.aspx

在你的情況,我建議這樣的:

private void LoadData(int iPersonID) 
{ 
    using (PeopleEntities ctx = new PeopleEntities()) 
    { 
     // AsNoTracking will avoid performance hit of change-tracking here... 
     // Since we're building-up a view, not an update case yet, you don't have to create 
     // proxies that will check for entity changing... 
     var query = ctx.People.AsNoTracking().SingleOrDefault(_people => _people.PersonID == iPersonID) 

     // Rendering comes into action 
     if (query != null) 
     { 
     TextBoxFirstName.Text = query.FirstName; 
     TextBoxLastName.Text = query.LastName; 
     } 
    } 
} 

private void SaveEmployee(int iPersonID = 0) 
{ 
    using (PeopleEntities ctx = new PeopleEntities()) 
    { 
     var query = ctx.Prople.SingleOrDefault(_person => _person.PersonID == iPersonID); 

     if (query != null) 
     { 
     query.FirstName = TextBoxFirstName.Text; 
     query.LastName = TextBoxLastName.Text; 
     ctx.SaveChanges(); 
     } 
    } 
} 
+0

使用 SelectSingleOrDefault(c => c.id == myid) – d1jhoni1b

0

「看來愚蠢我有這兩種方法各自查詢數據庫 到檢索和更新記錄」

你是絕對正確的Don't Repeat Yourself應該是 口頭禪 校長你應該努力遵循

這裏您已選擇檢索頁面加載事件中的數據,並在按鈕單擊事件中再次檢索它。這兩個事件都發生在WebPage的同一個實例中。您可以將它存儲在一個實例變量中並在按鈕單擊中重新使用它,或者您可以爲「延遲加載」的實體設置一個屬性。有各種各樣的方式來做到這一點。延遲加載是 可能 在這裏肯定是過度的,因爲 可能只會使用PageLoad中的屬性 應該理解什麼時候有必要去數據庫,什麼時候不需要。

當首次加載頁面時,需要轉到數據庫以獲取要顯示的數據。此後,當頁面回傳時,數據通常以表單值顯示。

當您更新記錄時,還需要轉到數據庫 - 在此示例中,當用戶單擊保存按鈕時會發生這種情況。

這裏是 延遲加載 東西,我可能不應該提到一個例子:

private People _Person; 

//lazy loaded property 
private People Person 
{ 
    get 
    { 
     if (_Person == null) 
      using (PeopleEntities ctx = new PeopleEntities()) 
       _Person = GetPerson(ctx); 

     //returning a Person that isn't updateable because we've disposed of the context  
     return _Person; 
    } 
} 

//Retrieve an updateable person 
private static object GetPerson(PeopleEntities ctx) 
{ 
    return (from a in ctx.People 
      where a.PersonID == int.Parse(Session["PersonID"] 
      select a).FirstOrDefault(); 
} 

你的代碼有另外一個問題是,你總是在設置在pageLoad的事件文本框從值數據庫。這意味着當你到達ButtonSave_Click事件時,返回的值已被數據庫中的內容覆蓋,並且更改不會被保存!

所以,你應該這樣做,而不是:

protected void Page_Load(object sender, EventArgs e) 
{ 
    if(!IsPostBack)//Only do this first time it's loaded 
    { 
     TextBoxFirstName.Text = Person.FirstName; 
     TextBoxLastName.Text = Person.LastName; 
    } 
} 

而且您點擊按鈕可以是這樣的:

protected void ButtonSave_Click(object sender, EventArgs e) 
{ 
    SavePerson(TextBoxFirstName.Text, TextBoxLastName.Text); 
} 

private SavePerson(string firstName, string lastName) 
{ 
    using (PeopleEntities ctx = new PeopleEntities()) 
    { 
     var person = GetPerson(ctx); 
     person.FirstName = firstName; 
     person.LastName = lastName; 
     ctx.SaveChanges(); 
    } 
} 

當你與你的編碼,你會發現,你要重複的SavePerson進展和GetPerson其他頁面上的代碼。 - 這是當你開始介紹存儲庫或圖層。 不要忘記 咒語 校長,你應該盡力遵循並將代碼移動到另一個類,以便可以重新使用它。

該類應該在PeopleRepository或某個其他層。最終你會發現PeopleRepository中的代碼看起來非常像MantraRepository中的代碼,你將不再需要爲不同類型重複自己。

那是當你應該開始使用「泛型」。您將PeopleRepositoryMantraRepository替換爲Repository<People>Repository<Mantra>,並將代碼定義爲類似於public class BaseRepository<T>之類的一個類。

你去那個旅程,雖然之前有關於實體框架位的另一件事 - 而不是

var query = (from a in ctx.People where a.PersonID == iPersonID select a).FirstOrDefault();

你應該/可以使用

var query = ctx.People.Find(iPersonID)

從這個源:Querying/Finding Entities

「DbSet上的Find方法使用主鍵值嘗試查找由上下文跟蹤的實體 。如果在 上下文中未找到實體,則將查詢發送到數據庫以在那裏查找實體 。如果在數據庫中的上下文或 中未找到實體,則返回空值。

找到的是從兩個顯著方式使用查詢不同:

,往返到數據庫中,如果與 定鍵的實體未在上下文中找到纔會進行。查找將返回 處於已添加狀態的實體。也就是說,查找將返回有 被添加到上下文,但尚未保存到數據庫的實體。」

現在,如果你想做出改變,因爲你沒有重複自己的任何地方你只需要更改GetPerson方法的代碼。

PS爲獲得創紀錄的可能會像這樣的事情,當你終於實現一個通用存儲庫中的代碼。

T e = Context.Set<T>().Find(id)

一號線使用

 xxx.xxx.SelectSingleOrDefault(c => c.AccountSenderID == userId_int) 

替換使用匿名lambda表達式(例如使用VAR)

    xxx.xxx.Select(c => new { c.FriendInvitationID,c.AccountSenderID, 
         c.Account1.AccountID, c.Account1.FirstName, c.Account1.LastName, c.Account1.Email, 
         c.FriendInvitationStatus, c.CreationDate }) 
        .Where(c => c.AccountSenderID == userId_int).ToList(); 

你沒有,即使匿名描述你的對象,讓他們所有

+0

對我來說,這裏的延遲加載將是一個主要的性能問題。您正在顯示數據以便檢索它! DRY原則是一個原則,應該作爲一個原則使用,而不是一個咒語。您無法爲每次致電人員創建一個方法,或者您始終會檢索所有內容。如果你只需要一個子集呢?好吧,它不再是DRY了......最後,這裏更好的方法是創建一個PersonRepository(通用存儲庫模式),這將有助於保持組織結構和避免代碼重複。 –

+0

@LordALMMa您在這裏提出延遲加載的問題是正確的,但不是因爲它是性能問題。也許你把我在這裏展示的例子與Entity Framework的延遲加載混淆了?根據我的經驗,許多開發人員在ASP.NET中與事件序列進行鬥爭,並在一個頁面的生命週期中多次訪問數據庫。當他們以這種方式進行編碼時引入延遲加載是重構它的一種方式。然而,將它作爲一種在ASP.NET中進行編程的標準方式並不合適,並且我已根據您的意見修改了我的答案 – Colin

+0

@LALALMMa再一次您是正確的! 「口頭禪:經常重複的陳述;一個特徵公式或者避免」。我怎麼可能與DRY結合使用。現在突破那些東西! :-) – Colin

0

試在這個意義上更具動態性(圖像你想要檢索一個json對象,並且同一個表有兩個不同的引用,在這種情況下,你必須聲明域,因爲它們會有相同的名字,只不過是一個)

相關問題