1

In short: What is a good method for setting up read-only data access from Silverlight to a MySQL database?


Here are the details of my situation:

I'm currently trying to set up a Silverlight application to present data from a MySQL database. Currently, I need to set-up read-only access to the MySQL database (I may set up other tables for complete CRUD functionality at a later, date, but for these particular tables, I'm only ever going to be concerned with the retrieve aspect).

I tried setting it up using RIA Services (CTP July 2009) with Entity Framework, but I had trouble debugging it and ended up trying to recompile the source code from the MySQL ADO.NET connector in order to install custom DLLs into the GAC. I wasn't able to get any of this stuff to work correctly.

My problem was that I had date values stored as 0000-00-00 in lots of my MySQL tables. The MySQL ADO.NET Connector throws an exception everytime it tries to bring down a row with an invalid date in it. I would try to recompile the connector (see links above), but that's feeling very much like a hack. I would try to update the values in the MySQL database to be within the appropriate spec for dates, but our IT manager (and effectively our DBA) does not want to do it.

I don't mind learning to work with LINQ (LINQ-to-what?), but I want to avoid concatenating my own strings of SQL commands. Because of the Date restrictions, I need a way to specify Case When orders.OrderDate = '0000-00-00' Then '0001-01-01' Else orders.OrderDate End for pretty much every date instance.

I'm especially interested to hear from folks who have worked with .NET and MySQL together. What will work in my situation?

Community
  • 1
  • 1
Ben McCormack
  • 32,086
  • 48
  • 148
  • 223
  • You could try setting zeroDateTimeBehavior=convertToNull in your connection string. This will send a null value for all invalid (i.e. 0000-00-00) dates. – Michael Todd Nov 24 '09 at 15:05
  • I believe the option is *Allow Zero Datetime* (http://dev.mysql.com/doc/refman/5.0/en/connector-net-programming-connection-options.html). I've tried this before but it doesn't work. I think the connector still throws an exception. – Ben McCormack Nov 24 '09 at 15:38
  • If I were you, I would write a back-end to proxy data from database. – faceclean Dec 07 '09 at 02:31
  • Or you could use an existing lightweight ORM and save yourself some time. Subsonic is really very simple to use. – Alex Dec 07 '09 at 10:04

4 Answers4

1

Why has no one suggested using a ORM to hide the mySQL details? Both NHibernate and Subsonic support mySQL. Both are very customisable in how they interact with the database and should allow you to cater for malformed dates.

By using an ORM your data objects are now POCOs, and you can use whatever you want to get the data to the Silverlight client. Vanilla web services or WCF should be fine. RIA services if you want to try out the bleeding edge.

IMHO, this will be simpler than setting up a mysql->php->xml->asp.net->silverlight chain.

Alex
  • 3,099
  • 6
  • 41
  • 56
0

My problem was that I had date values stored as 0000-00-00 in lots of my MySQL tables.

Can you just write Select NullIf( SomeDate, '0000-00-00') As SomeDate From SomeTable in your SQL queries? I don't know MySQL, but that's what I would do in T-SQL.

Jonathan Allen
  • 68,373
  • 70
  • 259
  • 447
  • If I were writing straight SQL, I would probably do something similar, such as `CASE WHEN SomeDate = '0000-00-00' Then '1901-01-01' Else SomeDate End As SomeDate`. However, my problem is setting up the plumbing so that I'm *not* doing straight SQL but sill have the flexibility to enter something like the `CASE` statement above as needed. – Ben McCormack Dec 03 '09 at 21:32
  • 2
    Can you wrap your tables in views? If so, that would effectively clean your data without forcing you to write SQL in a particular way. – Jonathan Allen Dec 04 '09 at 08:40
  • That's not a bad suggestion, but I just tested it and performance was terrible when trying to use the data field in the `Where` part of the SQL statement. I imagine this is because the `CASE` statement in the view must be evaluated before a query can be run against the resulting data set of the views. Either way, it's a difference of 31 ms versus 3078 ms. – Ben McCormack Dec 07 '09 at 20:20
  • Wow, that really sucks. How about just giving up and using a copy of SQL Express that is bulk-loaded from the real database on a regular basis? – Jonathan Allen Dec 08 '09 at 21:39
0

Here is what I did for a similar problem I was facing.

I used php to get data from the MySQL database and turned it into an XML file. I called that file from my silverlight app and used LINQtoXML to parse the data and make it available in my XAML controls. I am not a programmer by trade so maybe there is a better way to do it but this works for my app. Hope this helps. LINQ ROCKS!

Here is a portion of the code:

< ?php

header("Content-type: text/xml");

$grb_hostname = "host";
$grb_database = "dbName";
$grb_username = "dbUser";
$grb_password = "dbPwd";
$grb = mysql_connect($grb_hostname, $grb_username, $grb_password); 

mysql_select_db($grb_database, $grb);

$results = mysql_query("SELECT * FROM bursts ORDER BY bursts.id DESC");

$xmlOutput = "<?xml version=\"1.0\"?>\n"; 
$xmlOutput .= "<grbs>\n";

while($row = mysql_fetch_array($results)) {
    $xmlOutput .= "\t<grb id=\"".$row['id']."\" trigger=\"".$row['trigger']."\">\n";
    $xmlOutput .= "\t\t<grb_id>".$row['grb_id']."</grb_id>\n";
    $xmlOutput .= "\t\t<burst_ra>".$row['burst_ra']."</burst_ra>\n";
    $xmlOutput .= "\t\t<burst_dec>".$row['burst_dec']."</burst_dec>\n";
    $xmlOutput .= "\t</grb>\n";
}

$xmlOutput .= " < /grbs>"; // no space before /

echo $xmlOutput;

?>

then in my Silverlight I have the following:

private void LoadGrbs()

    {

        WebClient grbXmlFile = new WebClient();

        // Make sure the crossdomainpolicy.xml file exists on the remote server.
        grbXmlFile.DownloadStringAsync(new Uri("url_xml_generating_php_file", UriKind.Absolute));
        grbXmlFile.DownloadStringCompleted += new DownloadStringCompletedEventHandler(grbsXmlLoaded);
    }

    private void grbsXmlLoaded(object sender, DownloadStringCompletedEventArgs e)
    {
        processGrbXml(e.Result);
    }

    private void processGrbXml(string grbData)
    {
        XDocument grbs = XDocument.Parse(grbData);

        var query = from g in grbs.Descendants("grb")
                    select new
                        {
                            grbId = (string)g.Element("grb_id"),
                            grbDec = (string)g.Element("burst_dec")
                        };

        foreach (var grb in query)
        {
            grbListbox.Items.Add(grb.grbId);
        }

    }

grbListbox is a Listbox control in my Silverlight app.

Kamal
  • 383
  • 1
  • 6
  • 16
  • you can add validation code to you Silverlight app to check for incorrect dates. – Kamal Dec 04 '09 at 18:03
  • I appreciate the suggestion and like your creative use of Linq to XML. However, I'm trying to avoid queries to the server that involve `SELECT * FROM ...`. Even though the data is more "parseable" once in XML format, I'd have to download hundreds of thousands of records before I began parsing them. It would take way too much time. – Ben McCormack Dec 07 '09 at 20:08
-2

You should use RIA Services, the newest version came out last week, and it's included in the silverlight 4 beta now.

http://silverlight.net/getstarted/silverlight-4-beta/

You don't have to use the entity framework with RIA, there are other options. We do, but we use SQL Server so that might not be your favorite.

They have changed the errors some in the new RIA Stuff, so I'd recommend taking a 2nd look. Here's Brad Abrams' example from last week:

http://microsoftpdc.com/Sessions/CL21

Finally, if you're having a lot of trouble debugging, you could take a look at Fiddler. It's a program that watches the traffic and it can display you the errors you're having in a more obvious fashion.

thepaulpage
  • 4,614
  • 2
  • 25
  • 39
  • Thanks for the suggestion. I'll take another look at RIA Services with beta 4. However, I still need to find that link *between* the Domain Data Source and the MySQL DB. Somewhere along the way, I still have to be able to account for the invalid date. – Ben McCormack Nov 24 '09 at 15:35
  • I should also note: Entity Framework and RIA Services work *really well* with SQL Server since they are all Microsoft products. However, they don't play as nicely with MySQL, especially when there are issues with the MySQL data. I'd love to be able to use RIA Services, but if I feel like I'm hacking it to make it work, it may not be the best solution. – Ben McCormack Nov 24 '09 at 16:23
  • microsoft has been stressing that RIA Services (or WCF RIA Services) should play nicely with things that aren't Entity. If you check out Colin Blair's blog: http://www.riaservicesblog.com/Blog/ He talks about how he dislikes the Domain Data Source, and suggests (in my mind) better ways. You really are more playing with your data context. There's a video about using RIA with NHibernate instead of Entity and you could maybe look into that too. I think that this is it: http://microsoftpdc.com/Sessions/CL07 – thepaulpage Nov 24 '09 at 17:44
  • why the heck does this answer deserve negative votes? What did it ever do to you? – thepaulpage Apr 28 '10 at 16:21