Data Access on Mobile Devices

Download Report

Transcript Data Access on Mobile Devices

Mobile Data with the
Compact Framework
Shawn Wildermuth
Senior Consultant/Architect
Magenic Technologies
Who I Am
Shawn Wildermuth
([email protected])
C# MVP
INETA Speaker
Book Author
– “Pragmatic ADO.NET”
Editor of http://ONDotnet.com
This Presentation can be found at:
– http://adoguy.com/presentations
Agenda
How Mobile Data is Different
Deciding on a Solution
Limitations of the Compact Framework
Using SqlClient
Using SQL Server CE
Using Web Services
Data Binding on the Compact Framework
SQL Server CE 2005 (Yukon)
How Mobile Data is Different
The form factor is small
– Not much screen real estate
– Not much memory room
Needs to work disconnected
– Very few Mobile devices are always connected
– Smaller bandwidth usually when connected
Deciding on a Solution
Is a Smart Client the right solution?
– How much data manipulation is needed?
– Is offline support needed?
– Does state need to be shared with servers
If Smart Client, which Data Access?
– Options include:
 SQL Server Data Access
 SQL Server CE Data Access
 Web Services
Limitations of the CF
System.Data
– DataSets work fine
– Typed DataSets don’t
– No Design-time Support
System.Xml
– No XML Serialization Support
– OpenNETCF’s Xml Serialization isn’t Complete
System.Runtime.Serialization
– No SOAP or Binary Formatters
Limitations of the CF (2)
SqlClient
– Only on CE and Pocket PC (no SmartPhone)
– Requires Connectivity
SQL CE
– Only on CE and Pocket PC (no SmartPhone)
Web Services
– Support on all platforms
– Somewhat slower (not compressed like above)
Limitations of the CF (3)
DataSet is limited
– Merge() and GetChanges() are missing
– Deal with changes row-by-row
SQL Client Data Access
Remarkable similar to SqlClient in Full Fx
– Full Set of Adapter Functionality Supported
– Connection Strings are to real SQL Server
// Create the connection and command
SqlConnection conn = new SqlConnection("...");
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "SELECT * FROM Customers";
// Create a DataSet to put our results in
DataSet ds = new DataSet();
// Create the adapter
SqlDataAdapter da = new SqlDataAdapter(cmd);
// Fill it
da.Fill(ds, "Customers");
SQL Client Data Access (2)
Readers are also supported
– Same caveats apply to Mobile Apps
– Connected apps are hard on low bandwidth
// Create the connection and command
SqlConnection conn = new SqlConnection("...");
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "SELECT * FROM Customers";
// Use a Reader
try {
conn.Open();
SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read()) {
string name = rdr["CompanyName"].ToString();
}
}
finally {
conn.Close();
}
SQL Server CE
.NET CF / Managed Stack
VS .NET (VB.NET, C#)
ADO.NET
SQL Server CE Data Provider
CLR / .NET CF
OLEDB CE
SQL CE Edition v2.0
Data Provider
OLEDB
QP/Cursor Engine/ES
OLEDB
Client
Agent:
Replication
and
RDA
Storage Engine / Repl
Tracking
802.11b,
CDPD,
GSM,
CDMA,
TDMA, etc.
IIS
HTTP
Occasionally
Connected
CLIENT
SERVER
Server
Agent:
Replication
and
Remote
Data
Access
SQL Server CE (2)
Two Methodologies
– Remote Data Access
 Local Database
 Push and Pull Access from SQL Server
 Optional Change Tracking
– Merge Replication
 Use Replication Engine to Sync Changes
 Use Subscription model instead of RDA Model
 Allows vertical and horizontal partitioning
Setting up SQL Server CE - RDA
Integrates with IIS
– ISAPI Application to access remote data
 E.g. http://<machinename>/sqlce/sscesa20.dll
 Compresses results across the wire
– SqlCeRemoteDataAccess
 Takes an URL to the ISAPI App;
 and Connection String to database on mobile device
SqlCeRemoteDataAccess rda =
new SqlCeRemoteDataAccess("http://shawnw-lptd/sqlce/sscesa20.dll",
"Data Source=northwind.sdf");
SQL Server CE - RDA
Pulling Data to Mobile Device
–
–
–
–
Creation of the local DB with ad-hoc queries
Uses an OLEDB Connection String to connect
Pull to bring data from remote db to mobile db
Can include tracking information for updating
string rdaOleDbConnectString =
"Provider=sqloledb;Data Source=shawnw-lptd;" +
"Initial Catalog=Northwind;User Id=Sample;Password=ADONET";
rda.Pull("Customers", "SELECT * FROM Customers",
rdaOleDbConnectString, RdaTrackOption.TrackingOnWithIndexes);
rda.Pull("Products", "SELECT * FROM Products",
rdaOleDbConnectString, RdaTrackOption.TrackingOnWithIndexes);
rda.Pull("Orders", "SELECT * FROM Orders",
rdaOleDbConnectString, RdaTrackOption.TrackingOnWithIndexes);
rda.Pull("OrderDetails", "SELECT * FROM OrderDetails",
rdaOleDbConnectString, RdaTrackOption.TrackingOnWithIndexes);
SQL Server CE – RDA (2)
Uses local database storage
– Use of SqlCe* classes to access data normally
– Supports full suite of classes
// Create the connection and command
SqlCeConnection conn = new SqlCeConnection("...");
SqlCeCommand cmd = conn.CreateCommand();
cmd.CommandText = "SELECT * FROM Customers";
// Create a DataSet to put our results in
DataSet ds = new DataSet();
// Create the adapter
SqlCeDataAdapter da = new SqlCeDataAdapter(cmd);
// Fill it
da.Fill(ds, "Customers");
SQL Server CE – RDA (3)
Pushing data back
– Pushes changed rows back to remote DB
– Only if tracking is enabled
– Batching does all rows in single Tx
rda.Push("Customers",
rdaOleDbConnectString,
rda.Push("Products",
rdaOleDbConnectString,
rda.Push("Orders",
rdaOleDbConnectString,
rda.Push("OrderDetails",
rdaOleDbConnectString,
RdaBatchOption.BatchingOn);
RdaBatchOption.BatchingOn);
RdaBatchOption.BatchingOn);
RdaBatchOption.BatchingOn);
SQL Server CE – Merge Replication
Retrieves Data with Replication
– Fills the local DB from replication subscription
– Like RDA, uses ISAPI Application
– And local database connection for local cache
SqlCeReplication repl = new SqlCeReplication();
repl.InternetUrl
= "http://shawnw-lptd/sqlce/sscesa20.dll";
repl.Publisher
= "SHAWNW-LPTD";
repl.PublisherDatabase = "Northwind";
repl.PublisherLogin
= "sample";
repl.PublisherPassword = "ADONET";
repl.Publication
= "Northwind";
repl.Subscriber
= "OrderTaker";
repl.SubscriberConnectionString = "Data Source=northwind.sdf";
// Create the Local SSCE Database subscription
repl.AddSubscription(AddOption.CreateDatabase);
// Synchronize to the SQL Server 2000 to populate the Subscription
repl.Synchronize();
SQL Server CE – Merge Replication (2)
Local access is identical to RDA
– Uses same local database
– And same data access classes
// Create the connection and command
SqlCeConnection conn = new SqlCeConnection("...");
SqlCeCommand cmd = conn.CreateCommand();
cmd.CommandText = "SELECT * FROM Customers";
// Create a DataSet to put our results in
DataSet ds = new DataSet();
// Create the adapter
SqlCeDataAdapter da = new SqlCeDataAdapter(cmd);
// Fill it
da.Fill(ds, "Customers");
SQL Server CE – Merge Replication (3)
Merges back to remote db with Replication
– Uses same replication object as filled local db
– Synchronize uses Merge Replication
SqlCeReplication repl = new SqlCeReplication();
// ...
// Synchronize to the SQL Server 2000
// to populate the Subscription
repl.Synchronize();
SQL Server CE - Caveats
Several SQL Constructs don’t work
– Batch queries
– Object names with spaces (cannot use
delimiters)
 SELECT * FROM [Order Details]
– Queries are run with unchangable defaults
 QUOTED_IDENTIFIER_ON, ANSI_NULLS_ON,
ANSI_PADDING_ON, ANSI_NULL_DFLT_ON_ON,
CONCAT_NULL_YIELDS_NULL_ON
Web Services
SOAP Based Data Access
–
–
–
–
Only real data access on SmartPhones
Doesn’t require local connectivity
Use WriteSchema to pass whole structure of DS
Can use DataSets for updates
[WebMethod]
public XmlDocument Products() {
// ...
// Using WriteSchema to make sure the entire
// structure is included on client side
MemoryStream strm = new MemoryStream();
ds.WriteXml(strm, XmlWriteMode.WriteSchema);
strm.Position = 0;
XmlDocument doc = new XmlDocument();
doc.Load(strm);
return doc;
}
Web Services (2)
The Client consumes it normally
– Can use DataSets on the client for cache
– Use ReadSchema to fill in DS Structure
// Create the service
GetPhoneDataService theSvc = new
GetPhoneDataService();
// Load the data through the Web Service
XmlDocument doc = theSvc.Products();
// NOTE: Can't use a Typed DataSet Here
// Make it into a DataSet
DataSet ds = new DataSet();
XmlNodeReader rdr = new XmlNodeReader(node);
ds.ReadXml(rdr, XmlReadMode.ReadSchema);
// Must use AcceptChanges
// (ReadXml makes rows new)
ds.AcceptChanges();
Web Services (3)
Can store DataSet locally for cache
– This allows for the device to be disconnected
– Saving the data locally includes the changes
– Use DiffGrams to preserve the changes
// Write the data locally
ds.WriteXml("local.xml", XmlWriteMode.DiffGram);
// Read it locally
ds.ReadXml("local.xml", XmlReadMode.DiffGram);
Web Services (4)
Updating happens the same way
– Limitations of CF DataSets makes it chatty
– Prefer to use DiffGrams
 though whole DS are still sent
XmlDocument doc = new XmlDocument();
MemoryStream strm = new MemoryStream();
XmlTextWriter writer =
new XmlTextWriter(strm, System.Text.Encoding.UTF8);
ds.WriteXml(writer, XmlWriteMode.DiffGram);
strm.Position = 0;
doc.Load(strm);
[WebMethod]
public XmlDocument SaveChanges(XmlDocument doc) {
svc.SetDataSet(doc);
MyTypedDs ds = new MyTypedDs();
ds.ReadXml(doc, XmlReadMode.DiffGram);
DataSet updated = UpdateDataSet(ds);
return new XmlDataDocument(updated);
}
DataBinding
Performance Issues
– DataBinding on devices is very slow
 Manually filling-in controls much faster
 E.g. 2 seconds vs. 450ms
// This is faster
foreach (DataRow cust in ds.Tables["Customers"].Rows) {
listBox1.Items.Add(cust["CompanyName"]);
}
// This is slower, but more functional
listBox1.DataSource = ds.Tables["Customers"];
listBox1.DisplayMember = "CompanyName";
listBox1.ValueMember = "CustomerID";
DataBinding (2)
DataBinding is worth it sometimes
– If binding multiple items to a single source
– If you need a CurrencyManager
– If you need Master/Detail Binding
CurrencyManager mgr =
(CurrencyManager)listBox1.BindingContext[ds.Tables["Customers"]];
mgr.Position++;
DataTable tbl = ds.Tables["Customers"];
listBox.DataSource = tbl;
comboBox.DataSource = tbl;
textBox.Bindings.Add("Text", tbl, "CompanyName");
DataBinding (3)
– Use of background threads can help
// Launch the process on a background thread
ThreadPool.QueueUserWorkItem(new WaitCallback(BindDataToForm));
void BindDataToForm(object o) {
// Do Data Binding
}
SQL Server Mobile Edition
What’s New (Replacement for SQL CE)
– SQL Server 2005 Integration
 API Access to Merge Replication Engine
 Download only Tables (read-only)
 Partitioned Articles
– Synchronization
 Sync Progress API’s
 Column level Synchronization
 Variable Compression Levels
 Multiple Subscriptions per DB Table
SQL Server Mobile Edition (2)
What’s New (continued)
– Client Storage
 Improved ACID Support
 Improved Query Processor
– Client Performance
 Multi-User Support (allow sync while in use)
 SqlCeResultSet (Updatable Cursor)
– Client Support
 Additional Device Support
 Including SmartPhone
Questions?