The EntitySpaces Community

Share and learn about the EntitySpaces Architecture.
Welcome to The EntitySpaces Community Sign in | Join | Help
in
Home Forums Photos

wcf Updates not saving

Last post 02-19-2008, 3:05 PM by TrevorW. 16 replies.
Page 1 of 2 (17 items)   1 2 Next >
Sort Posts: Previous Next
  •  02-08-2008, 7:26 AM 7964

    wcf Updates not saving

    I am using client side proxies to send up the data.  Adds work fine.  Updates do not update unless the client sets the RowState to "Modified".  I would rather have the service set the RowState based on the service called, i.e. "updateRecord".  However, the data is coming up as Rowstate = unchanged.  If I set it to RowState=Modified on the server and save, nothing gets changed.  The modified columns.count = 0.  If I set the Rowstate on the client and send to server, the modifiedcolumns.count is correct.

    I did find that if I added this code, it will save.  But that kind of defeats the saving only modified columns feature. 

    if (promo.es.RowState == System.Data.DataRowState.Unchanged)
            promo.MarkAllColumnsAsDirty(System.Data.DataRowState.Modified);

     Any other suggestions?

    Filed under:
  •  02-08-2008, 9:35 AM 7965 in reply to 7964

    Re: wcf Updates not saving

    I will test this over the weekend. I'm sure we tested this however. If I find an issue we can probably get you a template patch.

    EntitySpaces | Twitter | BLOG | Please honor our Software License
  •  02-08-2008, 1:43 PM 7970 in reply to 7965

    Re: wcf Updates not saving

    Ok thanks.  By the way, I am using core version: 2007.0.730.0 with the template "fix" for setting esRowState in the proxystub that you provided in the forum.

    And I don't want to confuse this with the new clientside proxy objects recently released.  This calls the SetDirty() method when properties are changed. 

    What I am talking about above is the original proxyStub classes that have no call to SetDirty(), nor any other way of setting esRowState that I can tell (other than setting it explicitly), and are generated on the client with the svcutil utility.

  •  02-14-2008, 6:25 AM 8070 in reply to 7970

    Re: wcf Updates not saving

    Wow, you're on pretty old code. I'm afraid you're going to have to upgrade if you want a fix, HOWEVER, most likely the recent versions have already fixed the bug you are encountering. We have lots of folks using our proxy's that is why I was surprised at your post, What is preventing you from upgrading?

    EntitySpaces | Twitter | BLOG | Please honor our Software License
  •  02-14-2008, 7:44 AM 8072 in reply to 8070

    Re: wcf Updates not saving

    This code is in production now.  I'm addressing a reported "bug".  That's why I am reluctant to upgrade the dlls.

    However, I grabbed the latest code and regened my classes.  I looked at the new proxyStub classes and I don't see anything that would trigger setting the esrowstate value simply by setting a field value in the proxystub.  Is this being set (along with the modified columns collection) during the proxy-to-entity conversion in the ES core dll?

  •  02-14-2008, 7:46 AM 8073 in reply to 8072

    Re: wcf Updates not saving

    Okay, we will replicate and get back to you by tomorrow morning.

    EntitySpaces | Twitter | BLOG | Please honor our Software License
  •  02-14-2008, 4:24 PM 8075 in reply to 8073

    Re: wcf Updates not saving

    Okay, I just did a test here and everything seems to be working fine, let me post some stuff, for the code I tested.

     

    Code:
    // Load an Entity
    Employee emp = new Employee();
    if (emp.LoadByPrimaryKey(1))
    {
        EmployeeProxyStub serverProxy = new EmployeeProxyStub(emp);
    
        // 1) Serialize from the server using the EmployeeProxyStub 
        XmlSerializer sf = new XmlSerializer(typeof(EmployeeProxyStub));
        StringWriter sw = new StringWriter();
        sf.Serialize(sw, serverProxy);
        string packet = sw.ToString();
    
        // 2) Client Receives Packet, Deserialize's it into the Client.EmployeeProxyStub
        sf = new XmlSerializer(typeof(Client.EmployeeProxyStub));
        StringReader sr = new StringReader(packet);
        Client.EmployeeProxyStub clientProxy = sf.Deserialize(sr) as Client.EmployeeProxyStub;
    
        clientProxy.FirstName = "Speed";
        clientProxy.LastName = "Racer";
    
        // Serialize our Client.EmployeeProxyStub back into the packet 
        sf = new XmlSerializer(typeof(Client.EmployeeProxyStub));
        sw = new StringWriter();
        sf.Serialize(sw, clientProxy);
        packet = sw.ToString();
    
        // Deserialize the Packet back into our EmployeeProxyStub and pull .Entity from it
        sf = new XmlSerializer(typeof(EmployeeProxyStub));
        sr = new StringReader(packet);
        serverProxy = sf.Deserialize(sr) as EmployeeProxyStub;
    
        Employee theEmp = serverProxy.Entity as Employee;
    
        // Okay, at this point all columns should be marked as dirty in "theEmp"
        // ====> theEmp.es.ModifiedColumns.Count == 4
    }
     

    This is what a property looks like on one of the "Client" proxies.

     

    Code:
    public System.String LastName
    {
    	get
    	{
    		return _LastName;
    	}
    	set 
    	{
    		this.SetDirty();
    		this._LastName = value; 
    	}
    }
    private System.String _LastName;
     

    Notice that it calls SetDirty which does this:

     

    Code:
    private void SetDirty()
    {
    	if (this.esRowState == "Unchanged")
    	{
    		this.esRowState = "Modified";
    	}
    }
     

    When you Deserialize into the Server proxy this code is executed (it's in the core) when the RowState (which in this case is "Modified") is assigned:

     

    Code:
    protected string TheRowState
    {
        get
        {
            return this.theEntity.es.RowState.ToString();
        }
    
        set
        {
            switch (value)
            {
                case "Unchanged":
                    this.theEntity.AcceptChanges();
                    break;
    
                case "Added":
                    break;
    
                case "Modified":
                    List<string> modColumns = new List<string>(this.theEntity.es.ModifiedColumns);
                    this.theEntity.AcceptChanges();
                    this.theEntity.es.ModifiedColumns.AddRange(modColumns);
    
                    this.theEntity.es.RowState = DataRowState.Modified;
                    break;
    
                case "Deleted":
                    this.theEntity.AcceptChanges();
                    this.theEntity.MarkAsDeleted();
                    break;
            }
        }
    }
     

    I think you should take the first code snippet above and replace Employee with one of your objects and try it. You need to be serializing from the ServerProxy to the ClientProxy and then back to the ServerProxy.

    Let me know what you find out. In the case of ClientProxy's all columns will be marked as dirty whereas if you use the ServerProxy on both sides it tracks individual dirty states per column. 

     


    EntitySpaces | Twitter | BLOG | Please honor our Software License
  •  02-15-2008, 12:10 PM 8097 in reply to 8075

    Re: wcf Updates not saving

    Were you able to find anything out further on this? Did my post help?

    EntitySpaces | Twitter | BLOG | Please honor our Software License
  •  02-15-2008, 2:21 PM 8098 in reply to 8097

    Re: wcf Updates not saving

    My proxyStub are generated from the wcf tab in the main generated template, not the separate "clientproxy" template.  There is no "setDirty" operation in these proxies.  When the client app set a reference to the WCF service or uses service util, a service proxy is generated for the client app.  I am not sending the client any dll.

    I put together a sample I would like to send to you.  It uses the Pubs database.  How can I send you the zip file?

  •  02-15-2008, 2:33 PM 8099 in reply to 8098

    Re: wcf Updates not saving

    Ahh, your post said client side proxies, go ahead and send it to support@entityspaces.net

     


    EntitySpaces | Twitter | BLOG | Please honor our Software License
  •  02-17-2008, 6:00 PM 8102 in reply to 8099

    Re: wcf Updates not saving

    Okay, I got your sample app. It so refreshing to receive a sample app that I can simply compile and run, no missing pieces or complicated setup.

    [UPDATE]

    Your client app is not using the AuthorsProxyStub at all. It is our object that will drive the esRowState which needs to be set to modified in order for things to work. I manually set it on your event like this:

     

    Code:
    rivate void btnChange_Click(object sender, EventArgs e)
    {
    if (author != null)
    {
    author.AuLname = txtName.Text;
    author.esRowState = "Modified"; <== manual fix
    }
    }

     

    And it worked, however, this is not how it was meant to be used. Most people use "ES" on both sides, the client and the server. If not, you should use our light weight proxies on the client, they do not require EntitySpaces yet maintain the proper rowstate. However, you can if you want manually track set the esRowState. You are only using the Visual Studio generated proxy and not our object. I hope this makes sense. 


    EntitySpaces | Twitter | BLOG | Please honor our Software License
  •  02-18-2008, 7:30 AM 8105 in reply to 8102

    Re: wcf Updates not saving

    Thanks for taking a look at this Mike.  Yes, I agree that IF the client sets esRowstate= "Modified" then the update will be performed.  (I'm a little puzzled as to why a new record is saved even though the esRowState="Unchanged".)  I am not sure why you say the AuthorsProxyStub is not being used.  It IS the object being sent over the wire, or the representation therof, and is the object proxy that is generated by the Visual Studio.  It is just that soap/SrvcUtil.exe is serializing AuthorsProxyStub for me.  I'm not sure how you would otherwise pass the object back and forth from the service to the consumer without first altering its form.  The latest examples showing the ClientProxy classes seem to suggest that I manually serialize my objects into a string and then send them as a string over the wire, instead of letting WCF and SOAP serialize/deserialize the objects for me via their generated proxy objects.  This only works if you provide the client with a dll containing the classes representing the objects you are sending so that they can deserialize the string back into the original object.

    My situation is that, in true WCF fashion, I do not control my consumers or their code.  I may not even know that they are consuming my service.  Therefore, I cannot dictate they use a dll that I provide.  If I send them a string, they have no way to reconstruct the object. 

    To keep the coupling to a minumum, the consumer's only responsibility is to look at my end point, and conform to the message contract that I have defined for the requested service operation.  They generate the proxy of the contract, populate it, and send it back.

    It looks like I am left with my original hack: check the esRowstate when I get the object back, and if it is "Unchanged" (which it will always be), I can set all fields to modified.  Then the record will save.  Unfortunately, I won't be able to take advantage of most of the "smarts" in ES.

    Thanks again for taking time to work through this with me.

  •  02-18-2008, 7:48 AM 8106 in reply to 8105

    Re: wcf Updates not saving

    We have lots of users using ES in WCF scenarios and they do not have this problem. Our proxies are meant to serialize from the server into either our Server or Client proxy. How else could we know what has truly changed. There are others on this board using WCF just fine with ES, I would suggest that you search for WCF on our forums and find those guys and perhaps send them an message through the forums.

    If you are using a non ES class on the client how would we determine on the server side that the newly deserialized object is either modified/deleted/or added? Added is the default which is why that is working. Our proxies are really just great ways to serialize light weight packets back and forth and they maintain rowstate. They work well for WCF as well. However, I'm not a WCF guru. I think what our users are doing is return "strings" to the client and then deserializing them on the client with our lightweight proxies? The technique you are using might require your server to (after it receives the save request) to query the database (or perhaps cheat and see if the PK is non-null) and set the modified state to "Modified" ? I'm just thinking out loud here. You could also load it and compare it field manually setting the modifiedColumns collection? (I know Sad )

    We have time to address this for ES2008 and would love to hear some alternative suggestions. We'll put out a request for samples by our users.
     


    EntitySpaces | Twitter | BLOG | Please honor our Software License
  •  02-18-2008, 7:56 AM 8107 in reply to 8106

    Re: wcf Updates not saving

    Read my above comment first.

    You could, rather than having just a Save method, have an Add/Update/Delete method and you set things up appropriately in there? That would be quite easy to do and you could make it bullet proof that way.

    If you think about this is no different than a WebService, if you had a webservice and you used the VS created proxy on the client, how would ES know whether the data was added, updated or deleted, it couldn't? 


    EntitySpaces | Twitter | BLOG | Please honor our Software License
  •  02-18-2008, 8:32 AM 8109 in reply to 8107

    Re: wcf Updates not saving

    Your absolutely correct that it is a problem for the service to determine what has changed when a client app sends data through WCF.  Some have tried, with spotty success, to hash the object, and send it along to the client, and then compare it to a newly generated hash after a return trip to see if it has changed.   I'm not sure that is worth the effort, or doesn't introduce additional problems.

    I think you idea of separate add/update/delete operation contracts is the way to go for single records.  However, if I have a collection of objects and some are modified and some are deleted, I am hosed.  This effectively forces me to write all service operations as single entity operations.  OUCH. 

    As far as including the esRowState in the wcf proxy, as is the option on the generated template wcf tab, I'm not sure I see the benefit of including that as part of the proxyStub given the need to have different add/update/delete operations.  You can't really rely on the client app to set this, and if you have to set it anyway on the server to make sure, it is really not adding much value on the client.  (having it in the lightweight client proxy classes is useful however).

    Right now I have to figure out what to do with my service operations that send up a collection of objects and perform a Save().   

     

     

     

Page 1 of 2 (17 items)   1 2 Next >
View as RSS news feed in XML