views:

1256

answers:

5

I'm creating a simple Silverlight 2 application - a guestbook. I'm using MSSQL as the data source, I've managed to load the data but I can't find out how to add new rows (messages) to the database.

I crawled all the internet but didn't find any working solution. The SCMEssages table has four columns - MessageID, MessageDate, MessageAuthor and MessageText. Right now I have the following code in Service1 class (which implements IService1 interface) (not working though):

    public void SaveMessage(SCMessage message)
    {
        DataClasses1DataContext db=new DataClasses1DataContext();
        db.GetTable<SCMessage>().Attach(message);
        db.SubmitChanges();
    }

In the main class I'm simply calling this method:

    private void SendBtn_Click(object sender, RoutedEventArgs e)
    {
        SCMessage sm = new SCMessage
                           {
                               MessageAuthor = NameTB.Text,
                               MessageDate = DateTime.Now,
                               MessageText = TextTB.Text
                           };
        newMessages.Add(sm);

        ServiceReference1.Service1Client client = new Service1Client();
        client.SaveMessageAsync(sm);
    }

Could anybody help me? Thanks for any suggestions!

A: 

Is SCMessage decorated with the [DataContract] attribute or is it [Serializable]? Please provide us with the definition of SCMessage.

Terry Donaghe
A: 

SCMessage is name of a Data Class - I created a file from template "Linq to SQL Classes" (.dbml) and drag&dropped the SCMessages table to the Designer. It's decorated with the [DataContract] attribute and I set it's DataContext's Serialiation Mode property to Unidirectional. So the content of the SCMessage class is auto-generated, but here is as least a part of it:

[Table(Name="dbo.SCMessages")]
[DataContract()]
public partial class SCMessage : INotifyPropertyChanging, INotifyPropertyChanged
{

 private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);

 private int _MessageID;

 private string _MessageAuthor;

 private string _MessageText;

 private System.DateTime _MessageDate;

#region Extensibility Method Definitions
partial void OnLoaded();
partial void OnValidate(System.Data.Linq.ChangeAction action);
partial void OnCreated();
partial void OnMessageIDChanging(int value);
partial void OnMessageIDChanged();
partial void OnMessageAuthorChanging(string value);
partial void OnMessageAuthorChanged();
partial void OnMessageTextChanging(string value);
partial void OnMessageTextChanged();
partial void OnMessageDateChanging(System.DateTime value);
partial void OnMessageDateChanged();
#endregion

 public SCMessage()
 {
  this.Initialize();
 }

 [Column(Storage="_MessageID", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)]
 [DataMember(Order=1)]
 public int MessageID
 {
  get
  {
   return this._MessageID;
  }
  set
  {
   if ((this._MessageID != value))
   {
    this.OnMessageIDChanging(value);
    this.SendPropertyChanging();
    this._MessageID = value;
    this.SendPropertyChanged("MessageID");
    this.OnMessageIDChanged();
   }
  }
 }
jkottnauer
+1  A: 

I'm not sure I complete understand the context (like do you control your WCF service and/or your DB). But did you consider ADO.Net Data services? (also known as astoria) (http://msdn.microsoft.com/en-us/library/cc668792.aspx)

Then you don't need to create a webservice for it, it is already created for you.

Basically it is an easy way to access your data from within Silverlight and even be able to do queries from within silverlight.

There is already a bit of doc in blogs, for example: A quickstart is here: http://michaelsync.net/2008/01/15/consuming-adonet-data-service-astoria-from-silverlight How to update data can be seen here: http://michaelsync.net/2008/02/10/crud-operations-in-siverlight-using-adonet-data-service

A complete working example is here: http://www.silverlightdata.com/

Note that in a lot of examples on the web the silverlight proxy is generated using the command line, that is however not needed anymore, you can do it directly from within VS using "add service reference" to your project and pointing it to your ado.net data service

Hope this helps a bit?

Tjipke

Tjipke
I encountered those articles before but I didn't consider them helpful because I wanted to solve it the WCF-way. But now it seems to me as a lot easier way, I'll give it a try. Thanks a lot! I'll post here the results :-)
jkottnauer
A: 

And here's a little problem with Astoria - it doesn't work for me. I followed the Michael Sync's tutorial and made a few modifications, such as using of DataServiceQuery because WebDataQuery doesn't exist in final version of Astoria, etc. I ended up with two code snippets - the first is almost identical copy of the one in Michael Sync's article and the second one is using LINQ query instead of the CreateQuery method (I think both of these approaches lead to the same end). Here are the snippets:

SilverchatDBEntities entity =
                new SilverchatDBEntities(new Uri("http://localhost:65373/WebDataService1.svc", UriKind.Absolute));
            entity.MergeOption = MergeOption.OverwriteChanges;
            DataServiceQuery<SCMessages> messages = entity.CreateQuery<SCMessages>("SCMessages");

            messages.BeginExecute(
                result =>
                    {
                        var mess = messages.EndExecute(result);
                        foreach (var mes in mess)
                        {
                            MessagesLB.Items.Add(mes.MessageAuthor);
                        }
                    },
                null);

This doesn't do anything - it doesn't throw any exception and doesn't load any SCMessages neither. The second snippet is as follows:

            SilverchatDBEntities entity =
            new SilverchatDBEntities(new Uri("http://localhost:65373/WebDataService1.svc", UriKind.Absolute));
        var query = (DataServiceQuery<SCMessages>) from m in entity.SCMessages select m;
        query.BeginExecute(new AsyncCallback(result =>
                                                 {
                                                     try
                                                     {
                                                         var mes = query.EndExecute(result);

                                                         foreach (var r in mes)
                                                         {
                                                             MessagesLB.Items.Add(string.Format("{0}; {1} - {2}",
                                                                                                r.MessageDate.
                                                                                                    ToString(
                                                                                                    "d/M hh:mm",
                                                                                                    CultureInfo.
                                                                                                        InvariantCulture),
                                                                                                r.MessageAuthor,
                                                                                                r.MessageText));
                                                         }
                                                     }
                                                     catch (Exception ex)
                                                     {
                                                         MessageBox.Show(ex.Message);
                                                     }
                                                 }), null);

This one throws exception at the 'foreach' loop - 'Object reference not set to an instance of an object'. I have no idea what the problem could be.

jkottnauer
A: 

Chrasty,

I don't see any obvious errors yet. So in theory it shoulld work (I currently work almost daily with these kind of queries. A few questions: 1. can you use fiddler2 to see what is going over the wire. (If you don't know what fiddler is then google :-) and if after that you are using fiddler on localhost, then please add a '.' in the url in the browser (like http:\localhost.:1234\mywebsitehostingsilverlight.aspx), -> prevents an other google search) 2. Do you have a stack trace of the second one throwing an exception. 3. Did you try putting a breakpoint in your callback (first example) to see if it is called and with what result it is called

Hope these questions help a bit in solving the problem

Tjipke
I just tried putting a breakpoint in the callback as you suggested and it ended with this error: 'Could not load type 'SilverlightApplication1.ServiceReference1.SCMessage' from assembly 'SilverlightApplication1,...'I think this might be the problem...
jkottnauer
Do you have maybe two SCMessage types in your project? The from the proxy generated by data services and one of your original WCF service?
Tjipke
I don't because I created a new for solution for using data services, so there's nothing left from WCF.
jkottnauer