WCF处理对person对象的更新

时间:2013-07-11 15:13:15

标签: wcf web

我有这个非常常见的问题。我有POCO人课。

 [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和Age = 15的人事记录。

想象我有这样的客户端代码,在这种情况下我只想更新此人的年龄并保留所有其他字段

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

现在,一旦这段代码运行,我将遇到的问题是sql语句将运行并将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;}
    }

客户端代码现在就是

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

我知道这会有效,但我不喜欢这种方法,因为你现在正在处理updatePerson而不是Person。有没有人建议更好的方法?

5 个答案:

答案 0 :(得分:2)

您错过了识别某人的步骤。你在哪里想出id = 1?

例如:

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

答案 1 :(得分:2)

您可以让您的“UpdatePerson”类继承自“Person”。这样您就不必两次编写“Person”的定义。您仍然需要进行映射。不确定您是否使用AutoMapper或类似的东西,或者您只是手动编写映射。

[DataContract]
    public class UpdatePerson : Person
    {

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

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

    }

答案 2 :(得分:1)

嗯..您的服务应该只公开客户端将使用的数据。然后,这些数据将一起更新。不确定这是否适用于您的场景,但我想知道您是否应该考虑将服务划分为更加面向客户需求。

例如,您可以考虑将“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的操作(执行此操作,我认为您不需要附加实体)

请注意,此方法可能缺乏可伸缩性。您还可以对应在特定类中一起更新的参数进行分组。

这种方法是否适合您的需求?

答案 3 :(得分: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
         }

   }

答案 4 :(得分:0)

  

现在,一旦这段代码运行,我将遇到的问题是sql语句将运行并将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 , NoOfChildren=@NoOfChildrenCount where Id = Identifier
End