2

我有这个很常见的问题。我有 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。有人对更好的方法有任何建议吗?

4

5 回答 5

2

您错过了识别一个人的步骤。你从哪里得出 id = 1?

例如:

   PersonManagerService service=new PersonManagerService();
   Person p = service.findPersonByNumberOfChildren(5);
   p.Age = 26;
   service.UpdatePerson(p);
于 2013-07-17T17:31:29.020 回答
2

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

[DataContract]
    public class UpdatePerson : Person
    {

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

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

    }
于 2013-07-19T07:28:29.857 回答
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(这样做,我认为您不需要附加实体)

请注意,这种方法可能缺乏可扩展性。您还可以将应该在特定类中一起更新的参数分组。

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

于 2013-07-22T23:52:03.330 回答
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
         }

   }
于 2013-07-23T11:38:44.493 回答
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
于 2013-07-23T12:31:26.387 回答