没有元数据的实体SQL?

时间:2010-09-28 23:28:36

标签: sql entity-framework

我需要针对编译时未知的数据库模式针对各种数据库提供程序生成SQL查询。我看到实体框架已经完成了提供一种名为Entity SQL的SQL方言的艰苦工作,该方言在执行之前被转换为本机SQL,我希望以某种方式利用它。

理想情况下,我想生成ESQL,运行它并获得IDataReader,而实体框架则担心特定于提供程序的详细信息。但是,似乎没有办法在不提供SSDL,CSDL和MSL文件形式的元数据的情况下创建EntityConnection,并且在运行之前我不会发现数据库模式。

我的问题是,有没有办法在编译时没有任何关于数据库模式的信息来利用ESQL?如果有必要(并且可能),我将开放以编程方式从数据库生成元数据并缓存它。我也愿意接受任何可能比实体框架更适合我的需求的.NET工具。

感谢您的时间。

更新

感谢Alex的建议,我已经能够解决如何动态生成EntityConnection所需的元数据,而无需写出任何文件。结果,我能够完全按照我的意愿行事。现在我需要做的就是弄清楚如何从生成的元数据中提取有关我自己使用的可用表/视图的信息。

这是我的测试代码:

#r "System.Data.Entity"
#r "System.Data.Entity.Design"
#r "System.Transactions"

open System
open System.IO
open System.Data
open System.Data.EntityClient
open System.Data.Entity.Design
open System.Data.Mapping
open System.Data.Metadata.Edm
open System.Data.SqlClient
open System.Text
open System.Xml

let dbName = "Northwind"
let cnstr = sprintf "Server=.;Database=%s;Integrated Security=SSPI" dbName
let provider = "System.Data.SqlClient"

let mslText = StringBuilder()
let mslWriter = XmlWriter.Create(mslText)

let schemaGen = EntityStoreSchemaGenerator(provider, cnstr, dbName)
schemaGen.GenerateStoreMetadata() |> ignore

let modelGen = EntityModelSchemaGenerator(schemaGen.EntityContainer)
modelGen.GenerateMetadata() |> ignore
modelGen.WriteStorageMapping(mslWriter)
mslWriter.Close()

let mslReader = XmlReader.Create(new StringReader(mslText.ToString()))

let ssdlCollection = schemaGen.StoreItemCollection
let csdlCollection = modelGen.EdmItemCollection
let mslCollection = StorageMappingItemCollection(csdlCollection, ssdlCollection, [| mslReader |])

let mdw = MetadataWorkspace()
mdw.RegisterItemCollection(csdlCollection)
mdw.RegisterItemCollection(ssdlCollection)
mdw.RegisterItemCollection(mslCollection)

let sqlCn = new SqlConnection(cnstr)
let cn = new EntityConnection(mdw, sqlCn)
let cmd = cn.CreateCommand()
cmd.CommandText <- sprintf "SELECT p.ProductName FROM %sContext.Products AS p" dbName
cn.Open()
let reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)

while reader.Read() do
    printfn "%A" reader.["ProductName"]

reader.Close()
cn.Close()
sqlCn.Close()

1 个答案:

答案 0 :(得分:1)

有一种方法可以通过在运行时指向适当的元数据(CSDL,MSL和SSDL)来创建EntityConnection。

实际上,这是从对象层(CLR类)下载到实体客户端(eSQL和DataReader等)的主要好处之一。

为了帮助您入门,此This post向您展示了如何在运行时创建EntityConnection。