resueltos memoria manejo funcion ejercicios dinamicos dinamica arreglos c# .net asp.net-web-api odata

memoria - Servicio de odata dinámico en c#desde la capa de datos de tiempo de ejecución



manejo de memoria en c++ (2)

Hay un ejemplo que no requiere una clase predefinida disponible aquí: ODataUntypedSample , pero sí requiere un controlador predefinido.

He creado otra muestra de la aplicación de consola para poder consultar cualquier base de datos del servidor SQL usando OData. Utilicé este paquete nuget para leer el esquema y los datos de la base de datos: DatabaseSchemaReader . Necesitará el siguiente paquete nuget para poder compilarlo (más dependencias):

  • Microsoft.Owin.Hosting
  • Microsoft.Owin.Host.HttpListener
  • Microsoft.AspNet.WebApi.Owin
  • Microsoft.AspNet.OData

Aquí está el programa principal ligeramente modificado, por lo que declara las entidades Edm (para OData) de las tablas. Probé la muestra estándar Adventure Works 2014 pero debería funcionar en cualquier mesa con suerte:

class Program { private static HttpClient client = new HttpClient(); private static TableControllerSelector selector; private const string ServiceUrl = "http://localhost:12345"; private const string connectionString = @"Server=MYSQLSERVER;Database=AdventureWorks2014;Integrated Security=SSPI"; static void Main(string[] args) { using (WebApp.Start(ServiceUrl, Configuration)) { Console.WriteLine("Server is listening at {0}", ServiceUrl); RunSample(); Console.WriteLine("Press any key to continue . . ."); Console.ReadKey(); } } public static void Configuration(IAppBuilder builder) { HttpConfiguration configuration = new HttpConfiguration(); // create a special dynamic controller selector selector = new TableControllerSelector(configuration); IEdmModel model = TableController.GetEdmModel(connectionString, selector); configuration.Services.Replace(typeof(IHttpControllerSelector), selector); configuration.MapODataServiceRoute("odata", "odata", model); // needs using System.Web.OData.Extensions builder.UseWebApi(configuration); } public static void RunSample() { Console.WriteLine("1. Get Metadata."); GetMetadata(); Console.WriteLine("/n2. Get Entity Set."); using (var dbReader = new DatabaseReader(connectionString, "System.Data.SqlClient")) { foreach (var table in dbReader.AllTables()) { Console.WriteLine("/n 2.1 Get Entity Set ''" + table.Name + "''."); GetEntitySet(table.Name); } } } public static void GetMetadata() { HttpResponseMessage response = client.GetAsync(ServiceUrl + "/odata/$metadata").Result; PrintResponse(response); } public static void GetEntitySet(string tableName) { HttpResponseMessage response = client.GetAsync(ServiceUrl + "/odata/" + tableName + "?$filter=Id eq 1").Result; PrintResponse(response); } public static void PrintResponse(HttpResponseMessage response) { response.EnsureSuccessStatusCode(); Console.WriteLine("Response:"); Console.WriteLine(response); if (response.Content != null) { Console.WriteLine(response.Content.ReadAsStringAsync().Result); } } }

Y las clases especiales TableController y TableControllerSelector que permiten crear un modelo de Edm desde cualquier base de datos de SQL Server y crear controladores dinámicamente a partir de las entidades de Edm en ese modelo:

public class TableControllerSelector : DefaultHttpControllerSelector { private Dictionary<string, HttpControllerDescriptor> _tables = new Dictionary<string, HttpControllerDescriptor>(StringComparer.OrdinalIgnoreCase); public TableControllerSelector(HttpConfiguration configuration) : base(configuration) { Configuration = configuration; } public HttpConfiguration Configuration { get; private set; } public override HttpControllerDescriptor SelectController(HttpRequestMessage request) { string name = GetControllerName(request); if (name != null) // is it a known table name? { HttpControllerDescriptor desc; if (_tables.TryGetValue(name, out desc)) return desc; } return base.SelectController(request); } public void AddTable(string connectionString, DatabaseTable table) { if (connectionString == null) throw new ArgumentNullException("connectionString"); if (table == null) throw new ArgumentNullException("table"); // create a descriptor with extra properties that the controller needs var desc = new HttpControllerDescriptor(Configuration, table.Name, typeof(TableController)); desc.Properties["table"] = table; desc.Properties["connectionString"] = connectionString; _tables[table.Name] = desc; } } public class TableController : ODataController { // this will be called for standard OData access to collection public EdmEntityObjectCollection Get() { // get Edm type from request ODataPath path = Request.ODataProperties().Path; // ODataProperties() needs using System.Web.OData.Extensions IEdmType edmType = path.EdmType; IEdmCollectionType collectionType = (IEdmCollectionType)edmType; IEdmEntityType entityType = (IEdmEntityType)collectionType.ElementType.Definition; IEdmModel model = Request.ODataProperties().Model; ODataQueryContext queryContext = new ODataQueryContext(model, entityType, path); ODataQueryOptions queryOptions = new ODataQueryOptions(queryContext, Request); // TODO: apply the query option on the IQueryable here. // read all rows from table (could be optimized using query context) var table = (DatabaseTable)ControllerContext.ControllerDescriptor.Properties["table"]; var cnx = (string)ControllerContext.ControllerDescriptor.Properties["connectionString"]; return new EdmEntityObjectCollection(new EdmCollectionTypeReference(collectionType), ReadData(entityType, table, cnx)); } public static IList<IEdmEntityObject> ReadData(IEdmEntityType type, DatabaseTable table, string connectionString) { List<IEdmEntityObject> list = new List<IEdmEntityObject>(); // https://www.nuget.org/packages/DatabaseSchemaReader/ Reader reader = new Reader(table, connectionString, "System.Data.SqlClient"); reader.Read((r) => { EdmEntityObject obj = new EdmEntityObject(type); foreach (var prop in type.DeclaredProperties) { int index = r.GetOrdinal(prop.Name); object value = r.GetValue(index); if (Convert.IsDBNull(value)) { value = null; } obj.TrySetPropertyValue(prop.Name, value); } list.Add(obj); // uncomment these 2 lines if you''re just testing maximum 10 rows on a table //if (list.Count == 10) // return false; return true; }); return list; } public static IEdmModel GetEdmModel(string connectionString, TableControllerSelector selector) { EdmModel model = new EdmModel(); // create and add entity container EdmEntityContainer container = new EdmEntityContainer("NS", "DefaultContainer"); model.AddElement(container); // https://www.nuget.org/packages/DatabaseSchemaReader/ using (var dbReader = new DatabaseReader(connectionString, "System.Data.SqlClient")) { var schema = dbReader.ReadAll(); foreach (var table in schema.Tables) { EdmEntityType tableType = new EdmEntityType("NS", table.Name); foreach (var col in table.Columns) { var kind = GetKind(col); if (!kind.HasValue) // don''t map this continue; var prop = tableType.AddStructuralProperty(col.Name, kind.Value, col.Nullable); if (col.IsPrimaryKey) { tableType.AddKeys(prop); } } model.AddElement(tableType); EdmEntitySet products = container.AddEntitySet(table.Name, tableType); selector.AddTable(connectionString, table); } } return model; } // determine Edm kind from column type private static EdmPrimitiveTypeKind? GetKind(DatabaseColumn col) { var dt = col.DataType; if (col.DataType == null) return null; Type type = col.DataType.GetNetType(); if (type == null) return null; if (type == typeof(string)) return EdmPrimitiveTypeKind.String; if (type == typeof(short)) return EdmPrimitiveTypeKind.Int16; if (type == typeof(int)) return EdmPrimitiveTypeKind.Int32; if (type == typeof(long)) return EdmPrimitiveTypeKind.Int64; if (type == typeof(bool)) return EdmPrimitiveTypeKind.Boolean; if (type == typeof(Guid)) return EdmPrimitiveTypeKind.Guid; if (type == typeof(DateTime)) return EdmPrimitiveTypeKind.DateTimeOffset; if (type == typeof(TimeSpan)) return EdmPrimitiveTypeKind.Duration; if (type == typeof(decimal)) return EdmPrimitiveTypeKind.Decimal; if (type == typeof(byte) || type == typeof(sbyte)) return EdmPrimitiveTypeKind.Byte; if (type == typeof(byte[])) return EdmPrimitiveTypeKind.Binary; if (type == typeof(double)) return EdmPrimitiveTypeKind.Double; if (type == typeof(float)) return EdmPrimitiveTypeKind.Single; return null; } }

Intento crear un servicio de odata dinámico a partir de tablas en mis tablas que no se conocen hasta el tiempo de ejecución. Entonces, al inicio de mi aplicación web, un usuario selecciona una base de datos y en c # encuentro todas las tablas en esa base de datos.

Ahora la parte difícil es que quiero crear puntos finales de servicio odata para cada tabla en la base de datos y usarlos en consecuencia en mi aplicación web. El problema es que no sé cómo hacerlo dinámicamente. Hay muchos ejemplos con tablas de base de datos conocidas de compilación, pero en este caso, no las tendré hasta la primera vez que mi usuario use mi aplicación.

Cualquier ayuda o ideas son bienvenidas.


1. ¿Has intentado usar un diccionario? No sé si funciona con OData, solo una idea que surgió cuando todos los tipos de conexiones / deserializadores de datos con los que he trabajado también funcionaron con el diccionario.

2. La idea en la que estoy más interesado es recuperar una clase de la fuente de datos. Encontré algo aquí que podría ayudarte: clasifica a DataSet / DataSet en la clase , tal vez si no existen más obstáculos, usando los datos devueltos para construir una estructura para poner datos dentro ...

Perdón por ser algo incierto sobre las respuestas, solo ideas llegaron a mi cabeza, no sé mucho sobre OData. Espero que haya ayudado.