2013-07-11 30 views
2

我有這個很常見的問題。我有POCO人員課程。WCF處理人對象更新

[DataContract] 
public class Person 
{ 
[DataMember(IsRequired = true)] 
public int id{get;set;} 

[DataMember] 
public decimal? Age{get;set;} 

[DataMember] 
public decimal? NumberOfChildren{get;set;} 
} 

我有WCF操作是這個

public class PersonManagerService 
{ public void UpdatePerson(Person person) 
    { 
    //performs sql to update person in db 
    } 
} 

3)現在想象一下,在數據庫中有一個人紀錄,ID = 1,NumberOfChildren = 5,年齡= 15。

想象一下,我有這樣的客戶端代碼,在這種情況下,我只想更新人的年齡,並保留所有其他字段

Person p = new Person{id=1,Age=26;} 
    PersonManagerService service=new PersonManagerService(); 
    service.UpdatePerson(p); 

現在,一旦這個代碼運行,我將有問題的SQL statment將運行,並且將更新NumberOfChildren爲NULL。現在我知道我可以添加空檢查,以防止這是直截了當的。然而,我想要的是,在我確實指定字段具有空值的情況下,則更新應設置爲空值,如果未設置,則不對該字段執行任何操作。所以我在想,我需要做這樣的事情。創建具有這種

[DataContract] 
    public class UpdatePerson 
    { 
    [DataMember(IsRequired = true)] 
    public int id{get;set;} 

    public bool IsAgeSpecified{get;set;} 

    [DataMember] 
    public decimal? Age{get;set;} 

    public bool IsNumberOfChildrenSpecified{get;set;} 

    [DataMember] 
    public decimal? NumberOfChildren{get;set;} 
    } 

客戶端代碼的更新Person對象將是現在

UpdatePerson p = new UpdatePerson{id=1,IsAgeSpecified=true,Age=26;} 
    PersonManagerService service=new PersonManagerService(); 
    service.UpdatePerson(p); 

我知道這會工作,但我真的不喜歡這種方法,你現在用的updatePerson處理,而比一個人。有沒有人有更好的方法建議?

+0

是什麼驅動部分更新的要求?年齡/孩子是否可選,或者在進入時是未知的,並且將在以後知道? –

回答

1

Humm ..您的服務應該只公開客戶端將使用的數據。然後這些數據將一起更新。不確定這是否適用於您的情況,但我想知道是否應該考慮劃分您的服務以使其更加面向客戶需求。例如,您可以考慮將「Person」劃分爲面向服務真正更新的表示類。但是由於「Person」已經太小了,在這個特定的場景中,你可以打開屬性到應該一起更新的參數中。你可以得到這樣的:

public class PersonManagerService 
{ public void UpdatePerson(int personId, decimal age, decimal numberOfChildren); 
    { 
     //Instantiate new Person object filling the properties, say that age and numberOfChilren properties must be updated and call _UpdatePerson. 
    } 

    public void UpdatePerson(int personId, decimal age) 
    { 
     //Instantiate new Person object filling the age, say that age property must be updated and call _UpdatePerson. 
    } 

    public void UpdatePerson(decimal numberOfChildren, int personId) 
    { 
     //Instantiate new Person object filling the numberOfChildren, say that numberOfChilren property must be updated and call _UpdatePerson. 
    } 
    private void _UpdatePerson(Person person) 
    { 
      //do db stuffs 
    } 
} 

要說哪些屬性應該被更新,你可以不喜歡context.Entry(youreEntity).Property(e => e.SomeProperty).IsModified = true(這樣做,我覺得你並不需要附加的實體)

注意這種方法缺乏可擴展性。您也可以將應該在特定類中一起更新的參數分組。

此方法是否適合您的需求?

+0

只是爲了記錄,我看到代碼來更新特定屬性[在這裏](http://stackoverflow.com/questions/6115406/exclude-column-from-being-updateable-in-entity-framework-4-1-代碼優先) – Minduca

2

您錯過了識別某人的步驟。你在哪裏拿出id = 1?

例如:

PersonManagerService service=new PersonManagerService(); 
    Person p = service.findPersonByNumberOfChildren(5); 
    p.Age = 26; 
    service.UpdatePerson(p); 
2

你可以讓你的類 「的updatePerson」,從 「人」 繼承。這樣你就不必編寫兩次「Person」的定義。你仍然必須做這個映射。不知道您是否使用AutoMapper或類似的東西,或者您只是手動編寫映射。

[DataContract] 
    public class UpdatePerson : Person 
    { 

    [DataMember] 
    public bool IsAgeSpecified{get;set;} 

    [DataMember] 
    public bool IsNumberOfChildrenSpecified{get;set;} 

    } 
0

你可以使用反射,有一個方法,像

UpdatePropertiesofPerson(Person personTobeUpdated, List<string> listOfPropertiesToBeUpdated) 
    { 
     foreach (var propertyName in listOfPropertiesToBeUpdated) 
     { 
      var propertyValue = personTobeUpdated.GetType().GetProperty(propertyName).GetValue(personTobeUpdated, null); 

      //sql update statement here using the propertyName and the value 
     } 

    } 
0

現在,一旦這個代碼運行,我會是SQL statment將運行,並且將更新NumberOfChildren爲NULL的問題。

您可以修改您的存儲過程以通過從現有行中進行選擇,然後與從中間層發送的內容進行比較來處理該方案。這樣你的存儲過程也會運行得更好,因爲參數嗅探的次數會少一些。

Create Procedure UpdatePerson 
    InputAge int, NumChildren int, Identifier int 
    Begin 
     Declare @NoOfChildrenCount Int 
     Declare @Age Int 

     Select @NoOfChildrenCount= NoOfChildren, @Age= Age from Person where Id = Identifier 
     If InputAge <> @Age 
     set @Age = InputAge 
     If NumChildren <> @NoOfChildrenCount 
     set @NoOfChildrenCount = NumberChildren 

     Update Person Set Age = @Age , [email protected] where Id = Identifier 
End