Como muchos ya sabrán la clase DataSet en Silverlight no existe. No se porque Microsoft no incluyó esta clase en Silverlight, pero será supongo por tema de rapidez.

Navegando por la red encontré diversas maneras de trabajar con DataSet, pero la que mas me gusto es esta que explicare a continuación.

Nativamente no tenemos el objeto DataSet, pero si podemos pasarle una clase muy parecida desde el proyecto web.

[DataContract]

    public class DataColumnInfo

    {

        [DataMember]

        public string ColumnName { get; set; }


        [DataMember]

        public string ColumnTitle { get; set; }


        [DataMember]

        public string DataTypeName { get; set; }


        [DataMember]

        public bool IsRequired { get; set; }


        [DataMember]

        public bool IsKey { get; set; }


        [DataMember]

        public bool IsReadOnly { get; set; }


        [DataMember]

        public int DisplayIndex { get; set; }


        [DataMember]

        public string EditControlType { get; set; }


        [DataMember]

        public int MaxLength { get; set; }

    }

    [DataContract]

    public class DataTableInfo

    {

        [DataMember]

        public string TableName { get; set; }


        [DataMember]

        public List<DataColumnInfo> Columns { get; set; }


    }


    [DataContract]

    public class DataSetData

    {

        [DataMember]

        public List<DataTableInfo> Tables { get; set; }

        [DataMember]

        public string DataXML { get; set; }


        public static DataSetData FromDataSet(DataSet ds)

        {

            DataSetData dsd = new DataSetData();

            dsd.Tables = new List<DataTableInfo>();

            foreach (DataTable t in ds.Tables)

            {

                DataTableInfo tableInfo = new DataTableInfo { TableName = t.TableName };

                dsd.Tables.Add(tableInfo);

                tableInfo.Columns = new List<DataColumnInfo>();

                foreach (DataColumn c in t.Columns)

                {

                    DataColumnInfo col = new DataColumnInfo { ColumnName = c.ColumnName, ColumnTitle = c.ColumnName, DataTypeName = c.DataType.FullName, MaxLength = c.MaxLength, IsKey = c.Unique, IsReadOnly = (c.Unique || c.ReadOnly), IsRequired = !c.AllowDBNull };

                    if (c.DataType == typeof(System.Guid))

                    {

                        col.IsReadOnly = true;

                        col.DisplayIndex = -1;

                    }

                    tableInfo.Columns.Add(col);

               }

            }

            dsd.DataXML = ds.GetXml();

            return dsd;

        }


        public static DataSet ToDataSet(DataSetData dsd)

        {

            DataSet ds = new DataSet();

            UTF8Encoding encoding = new UTF8Encoding();

            Byte[] byteArray = encoding.GetBytes(dsd.DataXML);

            MemoryStream stream = new MemoryStream(byteArray);

            XmlReader reader = new XmlTextReader(stream);

            ds.ReadXml(reader);

            XDocument xd = XDocument.Parse(dsd.DataXML);

            foreach (DataTable dt in ds.Tables)

            {

                var rs = from row in xd.Descendants(dt.TableName)

                         select row;


                int i = 0;

                foreach (var r in rs)

                {

                    DataRowState state = (DataRowState)Enum.Parse(typeof(DataRowState), r.Attribute("RowState").Value);

                    DataRow dr = dt.Rows[i];

                    dr.AcceptChanges();

                    if (state == DataRowState.Deleted)

                        dr.Delete();

                    else if (state == DataRowState.Added)

                        dr.SetAdded();

                    else if (state == DataRowState.Modified)

                       dr.SetModified();

                    i++;

                }

            }

            return ds;

        }

    }

Lo que debemos hacer es trabajar con el objeto DataSet desde el proyecto web y en el momento que queramos pasarle el DataSet a Silverlight deberemos pasar el objeto DataSetData de esta manera:

public static DataSetData CreateDataSet( DataSet dataSet )

{

    return DataSetData.FromDataSet(dataSet);

}

Después para trabajar con este objeto en Silverlight es muy sencillo. Por ejemplo vamos a pasar los datos del DataSet a un DataGrid. Primero deberemos crear estas clases.

public class DynamicDataBuilder

    {

        private static System.Type BuildDataObjectType(DataColumnInfo[] Columns, string DataObjectName)

        {

            AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("AprimoDynamicData"), AssemblyBuilderAccess.Run);

            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("DataModule");


            TypeBuilder tb = moduleBuilder.DefineType(DataObjectName,

                                                    TypeAttributes.Public |

                                                    TypeAttributes.Class,

                                                    typeof(DataObject));


            ConstructorBuilder constructor = tb.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);

            foreach (var col in Columns)

            {

                string propertyName = col.ColumnName.Replace(' ', '_');

                Type dataType = System.Type.GetType(col.DataTypeName, false, true);

                if (dataType != null)

                {

                    FieldBuilder fb = tb.DefineField("_" + propertyName, dataType, FieldAttributes.Private);

                    PropertyBuilder pb = tb.DefineProperty(propertyName, PropertyAttributes.HasDefault, dataType, null);

                    MethodBuilder getMethod = tb.DefineMethod("get_" + propertyName,

                                                                MethodAttributes.Public |

                                                                MethodAttributes.HideBySig |

                                                                MethodAttributes.SpecialName,

                                                                dataType,

                                                                Type.EmptyTypes);


                    ILGenerator ilgen = getMethod.GetILGenerator();

                    //Emit Get property, return _prop

                    ilgen.Emit(OpCodes.Ldarg_0);

                    ilgen.Emit(OpCodes.Ldfld, fb);

                    ilgen.Emit(OpCodes.Ret);

                    pb.SetGetMethod(getMethod);

                    MethodBuilder setMethod = tb.DefineMethod("set_" + propertyName,

                    MethodAttributes.Public |

                    MethodAttributes.HideBySig |

                    MethodAttributes.SpecialName,

                    null,

                    new Type[] { dataType });

                    ilgen = setMethod.GetILGenerator();

                    LocalBuilder localBuilder = ilgen.DeclareLocal(typeof(String[]));

                    //Emit set property, _Prop = value;

                    ilgen.Emit(OpCodes.Ldarg_0);

                    ilgen.Emit(OpCodes.Ldarg_1);

                    ilgen.Emit(OpCodes.Stfld, fb);


                    //Notify Change:

                    Type[] wlParams = new Type[] { typeof(string[]) };

                    MethodInfo notifyMI = typeof(DataObject).GetMethod("NotifyChange",

                    BindingFlags.NonPublic |

                    BindingFlags.Instance,

                    null,

                    CallingConventions.HasThis,

                    wlParams,

                    null);


                    //NotifyChange Property change

                    ilgen.Emit(OpCodes.Ldc_I4_1);

                    ilgen.Emit(OpCodes.Newarr, typeof(String));

                    ilgen.Emit(OpCodes.Stloc_0);

                    ilgen.Emit(OpCodes.Ldloc_0);

                    ilgen.Emit(OpCodes.Ldc_I4_0);

                    ilgen.Emit(OpCodes.Ldstr, propertyName);

                    ilgen.Emit(OpCodes.Stelem_Ref);

                    ilgen.Emit(OpCodes.Ldarg_0);

                    ilgen.Emit(OpCodes.Ldloc_0);

                    ilgen.EmitCall(OpCodes.Call, notifyMI, null); // call nodifyChange function


                    ilgen.Emit(OpCodes.Ret);

                    pb.SetSetMethod(setMethod);

                }

            }

            System.Type rowType = tb.CreateType();

            //assemblyBuilder.Save("DynamicData.dll");

            return rowType;

        }


        public static IEnumerable GetDataList(DataSetData data)

        {

            if (data.Tables.Count() == 0)

                return null;


            DataTableInfo tableInfo = data.Tables[0];

            //string datatype = data.Tables.GetType().ToString();

            //string datatype2 = data.DataXML.GetType().ToString();

            System.Type dataType = BuildDataObjectType(tableInfo.Columns, tableInfo.Columns.GetType().ToString());


            //ObservableCollection<DataObject> l = new ObservableCollection<DataObject>();


            var listType = typeof(ObservableCollection<>).MakeGenericType(new[] { dataType });

            var list = Activator.CreateInstance(listType);


            XDocument xd = XDocument.Parse(data.DataXML);

            var table = from row in xd.Descendants(tableInfo.TableName)

                        select row.Elements().ToDictionary(r => r.Name, r => r.Value);


            foreach (var r in table)

            {

                var rowData = Activator.CreateInstance(dataType) as DataObject;

                if (rowData != null)

                {

                    foreach (DataColumnInfo col in tableInfo.Columns)

                    {

                        if (r.ContainsKey(col.ColumnName) && col.DataTypeName != typeof(System.Byte[]).FullName && col.DataTypeName != typeof(System.Guid).FullName)

                            rowData.SetFieldValue(col.ColumnName, r[col.ColumnName], true);

                    }

                }

                listType.GetMethod("Add").Invoke(list, new[] { rowData });

            }

            ObservableCollection<DataObject> l = list as ObservableCollection<DataObject>;

            return list as IEnumerable;

        }


        public static DataSetData GetUpdatedDataSet(IEnumerable list, DataTableInfo[] tables)

        {

            DataSetData data = new DataSetData();

            data.Tables = tables;

            //data.Tables = new ObservableCollection<DataSetInDataGrid.Silverlight.MyDataService.DataTableInfo>();

            //foreach (MyDataService.DataTableInfo t in tables)

            //{

            //    MyDataService.DataTableInfo table = new MyDataService.DataTableInfo { TableName = t.TableName };

            //    table.Columns = new ObservableCollection<DataSetInDataGrid.Silverlight.MyDataService.DataColumnInfo>();

            //    foreach (MyDataService.DataColumnInfo c in t.Columns)

            //    {

            //        table.Columns.Add(new MyDataService.DataColumnInfo{ColumnName= c.ColumnName, DataTypeName

            //    }

            //}


            XElement root = new XElement("DataSet");

            foreach (DataObject d in list)

            {

                if (d.State != DataObject.DataStates.Unchanged)

                {

                    XElement row = new XElement("Data", new XAttribute("RowState", d.State.ToString()));

                    PropertyInfo[] pis = d.GetType().GetProperties();

                    foreach (PropertyInfo pi in pis)

                    {

                        object val = pi.GetValue(d, null);

                        if (val != null)

                            row.Add(new XElement(pi.Name, val.ToString()));

                        else

                            row.Add(new XElement(pi.Name, ""));

                    }

                    root.Add(row);

                }

            }

            XDocument xdoc = new XDocument(new XDeclaration("1.0", "utf-8", "yes"), root);

            data.DataXML = xdoc.ToString();


            return data;

        }

    }

    public class DataObject : INotifyPropertyChanged, IEditableObject

    {

        protected Dictionary<string, object> _backupData = new Dictionary<string, object>();


        public enum DataStates

        {

            Unchanged = 2,

            Added = 4,

            Deleted = 8,

            Modified = 16,

        }

        public DataStates State { get; set; }

        public object GetFieldValue(string fieldname)

        {

            PropertyInfo pi = this.GetType().GetProperty(fieldname);

            if (pi != null)

                return pi.GetValue(this, null);

            return null;

        }

        public void SetFieldValue(string fieldname, object value, bool initial)

        {

            this.SetFieldValue(fieldname, value);

            if (initial)

            {

                this.State = DataStates.Unchanged;

                if (!_backupData.ContainsKey(fieldname))

                    _backupData.Add(fieldname, value);

            }


        }

        public void SetFieldValue(string fieldname, object value)

        {

            PropertyInfo pi = this.GetType().GetProperty(fieldname);

            if (pi != null)

            {

                object pValue = Convert.ChangeType(value, pi.PropertyType, null);

                if (pValue != null)

                    pi.SetValue(this, pValue, null);

            }

        }

        public void Delete()

        {

            this.State = DataStates.Deleted;

        }

        public void NewRow()

        {

            this.State = DataStates.Added;

        }

        protected void NotifyChange(params string[] properties)

        {

            if (PropertyChanged != null)

            {

                foreach (string p in properties)

                    PropertyChanged(this, new PropertyChangedEventArgs(p));

                this.State = DataStates.Modified;

            }

        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion


        #region IEditableObject Members


        public void BeginEdit()

        {

        }


        public void CancelEdit()

        {

            foreach (string fieldName in _backupData.Keys)

                this.SetFieldValue(fieldName, _backupData[fieldName], true);

        }


        public void EndEdit()

        {


        }


        #endregion

    }

Finalmente pasamos los datos al DataGrid.

dataGrid.ItemsSource = null;

dataGrid.Columns.Clear();

dataGrid.ItemsSource = DynamicDataBuilder.GetDataList(DataSetData);

Espero que os sirva :)

Actualización

DataSet en Silverlight II

Categories: , , , , ,

2 Responses so far.

  1. [...] This post was mentioned on Twitter by Mario Andújar Gómez and Etool Technologies, Emilio Torrens. Emilio Torrens said: Post en the .NET way: DataSet en Silverlight http://www.thedotnetway.net/?p=444 [...]

Leave a Reply


*

PUBLICIDAD

EMAIL





posts recientes

Instala la ultima versión...

Posted on ene - 23 - 2012

0 Comment

primer Vistazo al framework...

Posted on ene - 12 - 2012

0 Comment

Changelog de MongoMapper.NET

Posted on ene - 5 - 2012

0 Comment

Sponsors

  • Etooltech
  • Dingus Services
  • Etooltech
  • Dingus Services