简体   繁体   中英

Updating Disconnected Entity in Azure Table Storage

I am working a sample application using Windows Azure table storage. I will try to explain it using some code:

//GetStudent is a service call
StudentDetails student = this.GetStudent(studentID);

This code returns me a StudentDetails object with both PartitionKey and RowKey as null since both of those are not DataMembers in my DataContract.

//Update the student object
student.LastName = "New Last Name";
this.UpdateStudent(student);//Another service call

My update service code looks like below:

context.AttachTo(StudentDataServiceContext.studentTableName, student, "*");
context.UpdateObject(student);
context.SaveChangesWithRetries(SaveChangesOptions.ReplaceOnUpdate);

When I run this code I get the below error:

One of the request input is not valid

I did find a workaround to solve this and updated the UpdateService code like below:

StudentDetails temp = (from c in context.StudentTable
                       where c.PartitionKey == "Student" && c.RowKey == student.ID
                       select c).FirstOrDefault();
//Copy each and every property from student object to temp object
temp.LastName = student.LastName;
context.UpdateObject(temp);
context.SaveChangesWithRetries(SaveChangesOptions.ReplaceOnUpdate);

This works fine and the object gets updated in the table storage.

But is there not a better way of doing this? Why doesn't the AttachTo function work in my case?

EDIT

Just to make my question more clear, here is my StudentDetails Class:

[DataContract]
public class StudentDetails
{
        public string PartitionKey { get; set; }
        public string RowKey { get; set; }

        [DataMember]
        public string First Name { get; set; }

        [DataMember]
        public string Last Name { get; set; }

        [DataMember]
        public string ID { get; set; }
}

And below is my GetStudent method:

BasicHttpBinding myBinding = new BasicHttpBinding();
EndpointAddress myEndpoint = new EndpointAddress(RoleEnvironment.GetConfigurationSettingValue("StudentServiceURI"));
ChannelFactory<IPatientService> myChannelFactory = new ChannelFactory<IStudentService>(myBinding, myEndpoint);
IStudentService proxy = myChannelFactory.CreateChannel();
student = proxy.GetPatient(studentID);
((IClientChannel)proxy).Close();
myChannelFactory.Close();

I feel the problem is with my GetStudent's channel factory call which is missing something related to service's context. I just don't know what.

You said that the Student object returned doesn't have a PartitionKey and RowKey set when it is returned. You then try to update that object. If you haven't set the PartitionKey and RowKey yourself before calling .Update() this will fail as the underlying REST API depends on these.

It occurs when testing the application with empty tables in development storage. This is because Development Storage currently requires the schema for an entity stored in a table to have been previously defined before you are allowed to query it.

Workaround

The workaround is simple, we just need to insert, and then delete, a dummy row into the Windows Azure tables if the application is running in the development fabric. During the initialization of the web role, it is a good idea if the application checks whether it is running against local development storage, and if this is the case, it adds, and then deletes, a dummy record to the application's Windows Azure tables (It will be done just the first time, per Entity, when working against the Development Storage).

That code can be added using an extension method, for instance.

More info on:

http://msdn.microsoft.com/en-us/library/ff803365.aspx

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM