2015-05-01 7 views
18

मैं अपने टेबल में टेबल से गतिशील ओडाटा सेवा बनाने की कोशिश कर रहा हूं जो रनटाइम तक ज्ञात नहीं है। तो मेरे वेब एप्लिकेशन की शुरुआत में, उपयोगकर्ता डेटाबेस का चयन करता है और सी # में मुझे उस डेटाबेस में सभी टेबल मिलती हैं।रनटाइम डेटा परत से सी # में डायनामिक ओडाटा सेवा

अब कठिन हिस्सा है कि मैं डेटाबेस में प्रत्येक तालिका के लिए ओडाटा सेवा एंडपॉइंट बनाना चाहता हूं और उनके अनुसार अपने वेब एप्लिकेशन में उनका उपयोग करना चाहता हूं। समस्या यह है कि मुझे नहीं पता कि इसे गतिशील तरीके से कैसे किया जाए। डेटाबेस टेबल ज्ञात संकलन समय के साथ कई उदाहरण हैं, लेकिन इस मामले में, मेरे पास तब तक नहीं होगा जब तक मेरा उपयोगकर्ता मेरे आवेदन का उपयोग नहीं करता।

किसी भी मदद या विचारों का अत्यधिक स्वागत है।

+0

आप पर http://www.odata.org/blog/restier-a-turn-key-framework-to-build-restful-service/ मुझे मिल गया एक नज़र लिया है एक ही स्थिति, और इस मामले के समाधान के लिए देख रहा हूँ। –

+0

कृपया स्पष्ट करें: क्या आप सेवा शुरू होने के बाद ओडाटा सेवा डेटाबेस और तालिकाओं के सेट को खोजने के बारे में बात कर रहे हैं? या ओडाटा सेवा अपने पूरे समय में ऊपर और नीचे आने वाले डेटाबेस का समर्थन करने वाली है? – lencharest

उत्तर

11

एक ऐसा उदाहरण है जिसके लिए यहां उपलब्ध एक पूर्वनिर्धारित कक्षा की आवश्यकता नहीं है: ODataUntypedSample, लेकिन इसके लिए एक पूर्वनिर्धारित नियंत्रक की आवश्यकता होती है।

मैंने ओडाटा का उपयोग कर किसी SQL सर्वर डेटाबेस से क्वेरी करने में सक्षम होने के लिए इसे एक और कंसोल एप्लिकेशन नमूना बनाया है। मैंने डेटाबेस स्कीमा और डेटा पढ़ने के लिए इस nuget पैकेज का उपयोग किया है: DatabaseSchemaReader। आप नीचे दिए गए nuget पैकेज की आवश्यकता होगी यह (प्लस निर्भरता) के निर्माण के लिए सक्षम होने के लिए:

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

यहां मुख्य कार्यक्रम थोड़ा संशोधित तो यह Edm वाणी टेबल से संस्थाओं (OData के लिए) है। मैं मानक नमूना Adventure Works 2014 परीक्षण किया है, लेकिन यह उम्मीद है कि किसी भी मेज पर काम करना चाहिए:

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); 
     } 
    } 
} 

और विशेष TableController और TableControllerSelector वर्गों है कि किसी भी एसक्यूएल सर्वर डेटाबेस से एक EDM मॉडल बनाने के लिए अनुमति देते हैं, और डायनामिक रूप से नियंत्रकों बनाने उस मॉडल में EDM संस्थाओं:

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; 
    } 
} 
+0

वाह यह वास्तव में "RosettaStone" था जिसे मैं ढूंढ रहा था! धन्यवाद! –

+0

इस नमूने के लिए धन्यवाद !! बस एक त्वरित नोट - नवीनतम संस्करणों में, अनुरोध से मॉडल प्राप्त करने के लिए आपको 'IEdmModel मॉडल = Request.GetModel();' IEdmModel मॉडल = Request.ODataProperties() मॉडल के बजाय उपयोग करना चाहिए। TableController.Get()) –

+0

@ गोंसालोबोरेगा - हाँ :-), यह मेरी टिप्पणी में भी था: https://github.com/OData/ODataSamples/issues/50#issuecomment-258799428 –

2

1. क्या आपने एक शब्दकोश का उपयोग करने की कोशिश की है? मुझे नहीं पता कि यह ओडाटा के साथ काम करता है, सिर्फ एक विचार जो कि सभी प्रकार के डेटा कनेक्शन/deserialisers के रूप में आया है, साथ ही मैंने शब्दकोश के साथ भी काम किया है।

2. विचार मैं और अधिक में हूँ,, मैं यहाँ कुछ है कि आप मदद कर सकता है पाया डेटा स्रोत से एक वर्ग को पुनः प्राप्त करने के लिए है: Class to DataSet/DataSet to class, हो सकता है अगर कोई और अधिक बाधाएं मौजूद हैं, डेटा का उपयोग कर निर्माण करने के लिए लौट आए डेटा को अंदर रखने के लिए एक संरचना ...

किसी भी तरह के उत्तरों के बारे में अनिश्चित होने के लिए खेद है, सिर्फ मेरे सिर पर विचार आया, मुझे ओडाटा के बारे में बहुत कुछ पता नहीं है। उम्मीद है कि यह मदद की।

संबंधित मुद्दे