locked
Updating objects RRS feed

  • Question

  • I know that to update an object, I first need to query to retrieve it, set changed property values, and invoke the DataContext.UpdateObject.

     

    In my information system, the object is first created with a subset of its properties. It passes through several service layers to finally come back to be updated in the datasource with all properties set.

    I'm looking for a 'copy mechanism' to update all fieds of the tracked object that may have changed from a modified object without overwriting every single one by hand.

     

    Pseudo Code :

     

    Code Snippet

            public MyObjectType Update(MyObjectType data)
            {
                DataServiceContext ctx = new DataServiceContext(new Uri(Configuration.GetStoreURI()));
                ctx.MergeOption = MergeOption.AppendOnly;
               
                // We first need to track the object back in the context using its primary key
                DataServiceQuery<MyObjectType > test = ctx.CreateQuery<MyObjectType >("Data");
                var c1 = (from c in test
                          where c.UniqueID  == data.UniqueID
                          select c).First();

      // How to update all fields ????

                c1 = data;

     

      // Update Object in the store

                ctx.UpdateObject(c1);
            }

     

     

     

    Any help appreciated.

    TIA.

    Olivier.

    Friday, September 19, 2008 9:19 AM

Answers

  • Why can't you use reflection to do this? You can walk all the properties and update them or just update the ones which have changed. Reflection allows you to not know what properties a type has and do this in a generic fashion.

     

    Code Snippet

    foreach (PropertyInfo property in c1.GetProperties(BindingFlags.Public))

    {

        object value1 = property.GetValue(data, null);

        property.SetValue(c1, value1, null);

    }

     

     

    If you just want to set the modified fields, you can compare the values and then set them.

     

    Hope this helps.

     

    Thanks

    Pratik

    Friday, September 19, 2008 10:49 PM
    Moderator

All replies

  • a kind of Clone ?

     

    I dont know if there is already a way to do that but in my opinion you can :

     

    create your own xslt file to generate a c# file from the webdataservice.svc/$metadata url.

    The xsl will create easily and automatically this kind of method to do that for you.

     

    You need to have msxsl.exe

     

    then just add this kind of command in you pre build event :

     

     

     

     

    Code Snippet
    msxsl.exe http://localhost:30047/WebDataService.svc/$metadatahttp://localhost:30047/WebDataService.svc/$metadata">http://localhost:30047/WebDataService.svc/$metadata</A< A>> $(ProjectDir)EntitiesGeneratorXSLTFile.xslt -o $(ProjectDir)BusinessEntities.Custom.cs

     

     

     

     

    Your xsl will look like :

     

    Code Snippet

    <?xml version="1.0" encoding="UTF-8" ?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                     xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
               xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx"
               xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
                     xmlns:schema="http://schemas.microsoft.com/ado/2007/05/edm"
               xmlns:xs="http://www.w3.org/2001/XMLSchema">
     
      <xs:import namespace="http://schemas.microsoft.com/ado/2007/05/edm" />
      <xsl:output method="text"/>
     
     
      <!-- ROOT OF DOCUMENT -->
      <xsl:template match="/edmx:Edmx">
     
        <xsl:apply-templates select="edmx:DataServices" />
        <xsl:apply-templates select="edmx:Queries">
        </xsl:apply-templates>

      </xsl:template>


      <!--SERVICES-->
      <xsl:template match="edmx:DataServices">

        <xsl:apply-templates select="schema:Schema">
          <xsl:sort select="@Namespace"/>
        </xsl:apply-templates>

      </xsl:template>


      <!-- NAMESPACE -->
      <xsl:template match="schema:Schema">
        <xsl:text>

    &#10;&#10;</xsl:text>
        <xsl:text>namespace _temp</xsl:text><xsl:value-of select="@Namespace"/>
        <xsl:text>
    {</xsl:text>


        <xsl:apply-templates select="schema:EntityType">
          <xsl:sort select="@Name"/>
        </xsl:apply-templates>


        <xsl:text>&#10;}&#10;</xsl:text>

      </xsl:template>


      <!--CLASSES-->
      <xsl:template match="schema:EntityType">
        <xsl:text>&#10;&#10;</xsl:text>
        <xsl:text>&#9;#region class </xsl:text>
        <xsl:value-of select="@Name"/>
        <xsl:text>&#10;&#10;</xsl:text>
       
        <xsl:text>&#9;[global::System.Serializable()]</xsl:text>
        <xsl:text>&#9;[global::System.Data.Services.Common.DataServiceKeyAttribute(</xsl:text>
        <xsl:for-each select="schema:Key/schema:PropertyRef">
          <xsl:text>"</xsl:text>
          <xsl:value-of select="@Name"/>
          <xsl:text>"</xsl:text>
        </xsl:for-each>
        <xsl:text>)]&#10;</xsl:text>
        <xsl:text>&#9;public partial class </xsl:text>
        <xsl:value-of select="@Name"/>
        <xsl:text> : global::System.ComponentModel.INotifyPropertyChanged
    &#9;{&#10;</xsl:text>

     

    //add you own template to add you clone method

    public void CloneFromFriend(<xsl:value-of select="@Name"/> instanceToClone)

    {

    //make a <xsl:foreach /> block here to travel through the

    //class properties and clone it.

    }

     

     

           <xsl:text>&#10;&#9;}&#10;</xsl:text>
        <xsl:text>&#10;&#10;&#9;#endregion //class&#10;</xsl:text>

      </xsl:template>

    </xsl:stylesheet

     

     

     

    good luck

     

     

     

     

     

    Friday, September 19, 2008 3:48 PM
  • Why can't you use reflection to do this? You can walk all the properties and update them or just update the ones which have changed. Reflection allows you to not know what properties a type has and do this in a generic fashion.

     

    Code Snippet

    foreach (PropertyInfo property in c1.GetProperties(BindingFlags.Public))

    {

        object value1 = property.GetValue(data, null);

        property.SetValue(c1, value1, null);

    }

     

     

    If you just want to set the modified fields, you can compare the values and then set them.

     

    Hope this helps.

     

    Thanks

    Pratik

    Friday, September 19, 2008 10:49 PM
    Moderator