Search code examples
linqwindows-phone-7linq-to-sqlsql-server-cewindows-phone

Windows Phone SQL Server CE - Retrieve underlying database schema for upgrade


Windows Phone 7.1 supports SQL Server CE and LINQ to SQL, as well as upgrading the database via DatabaseSchemaUpdater.

On other platforms I would read the database schema tables (e.g. sys.objects) to view the current schema and work out what tables/columns need to be upgraded.

Given that no direct SQL access is allowed on Windows Phone, how can retrieve the current database schema?


Solution

  • SQL Server CE still includes the INFORMATION_SCHEMA.TABLES and INFORMATION_SCHEMA.COLUMNS tables, but it is a little tricky to access them as no direct SQL access is allowed.

    However, you can create a DataContext which maps to these tables:

    public class SchemaContext : DataContext
    {
        public SchemaContext()
            : base("Data Source=isostore:/Database.sdf")
        {
            if (!this.DatabaseExists())
            {
                throw new InvalidOperationException("Cannot use the SchemaContext on a database which doesn't exist");
            }
        }
    
        public Table<Table> Tables;
        public Table<Column> Columns;
    
        [Table(Name = "INFORMATION_SCHEMA.Columns")]
        public class Column
        {
            [Column(Name = "TABLE_NAME")]
            public string TableName { get; set; }
    
            [Column(Name = "COLUMN_NAME")]
            public string Name { get; set; }
    
            [Column(Name = "DATA_TYPE")]
            public string DataType { get; set; }
    
            [Column(Name = "ORDINAL_POSITION")]
            public int OrdinalPosition { get; set; }
    
            [Column(Name = "IS_NULLABLE")]
            public string IsNullableString { get; set; }
    
            public bool IsNullable
            {
                get { return this.IsNullableString == "YES"; }
                set { this.IsNullableString = value ? "YES" : "NO"; }
            }
    
        }
    
        [Table(Name = "INFORMATION_SCHEMA.Tables")]
        public class Table
        {
            [Column(Name = "TABLE_NAME")]
            public string Name { get; set; }
    
            [Column(Name = "TABLE_TYPE")]
            public string Type { get; set; }
        }
    }
    

    You can then read the schema with the following code:

    using (var schemaContext = new SchemaContext())
    {
        foreach (var table in schemaContext.Tables)
        {
    
        }
    }
    

    It's important to create a separate context for these tables, as otherwise the DataContext.CreateDatabase call will attempt to create these schema tables, which will fail.