gpt4 book ai didi

c# - 是否可以在不连接数据库的情况下检索 MetadataWorkspace?

转载 作者:行者123 更新时间:2023-12-02 04:22:07 25 4
gpt4 key购买 nike

我正在编写一个测试库,需要针对给定的 DbContext 类型遍历 Entity Framework MetadataWorkspace。但是,由于这是一个测试库,我不想连接到数据库 - 它引入了测试环境中可能无法使用的依赖项。

当我尝试像这样获取对 MetadataWorkspace 的引用时:

var metadata = ((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace;

我收到一个SqlException:

An exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll but was not handled in user code

Additional information: A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26 - Error Locating Server/Instance Specified)

是否可以在没有连接字符串的情况下执行我想要的操作?

最佳答案

是的,您可以通过向上下文提供虚拟连接字符串来做到这一点。请注意,通常当您调用 DbContext 的无参数构造函数时,它会在主应用程序的 app.config 文件中查找带有上下文类名称的连接字符串。如果是这种情况,并且您无法更改此行为(就像您不拥有相关上下文的源代码一样) - 您将必须使用该虚拟连接字符串更新 app.config (也可以在运行时完成)。如果您可以使用连接字符串调用 DbContext 构造函数,则:

var cs = String.Format("metadata=res://*/{0}.csdl|res://*/{0}.ssdl|res://*/{0}.msl;provider=System.Data.SqlClient;provider connection string=\"\"", "TestModel");
using (var ctx = new TestDBEntities(cs)) {
var metadata = ((IObjectContextAdapter)ctx).ObjectContext.MetadataWorkspace;
// no throw here
Console.WriteLine(metadata);
}

因此,您仅提供对于获取元数据工作区重要的参数,并提供空连接字符串。

更新:经过更多思考,您根本不需要使用此类技巧并实例化上下文。

public static MetadataWorkspace GetMetadataWorkspaceOf<T>(string modelName) where T:DbContext {
return new MetadataWorkspace(new[] { $"res://*/{modelName}.csdl", $"res://*/{modelName}.ssdl", $"res://*/{modelName}.msl" }, new[] {typeof(T).Assembly});
}

在这里,您只需直接使用 MetadataWorkspace 类的构造函数,将其路径传递给目标元数据元素以及要检查的程序集。请注意,此方法做出了一些假设:元数据工件嵌入到资源中(通常是这样,但可以是外部的,或者嵌入到另一个路径下),并且所需的所有内容都与 Context 类本身位于同一个程序集中(理论上您可能有一个程序集中的上下文和另一个程序集中的实体类,等等)。但我希望你能明白。

更新2:获取代码优先模型的元数据工作空间有点复杂,因为该模型的 edmx 文件是在运行时生成的。它在哪里以及如何生成是实现细节。但是,您仍然可以通过一些努力获得元数据工作区:

    public static MetadataWorkspace GetMetadataWorkspaceOfCodeFirst<T>() where T : DbContext {
// require constructor which accepts connection string
var constructor = typeof (T).GetConstructor(new[] {typeof (string)});
if (constructor == null)
throw new Exception("Constructor with one string argument is required.");
// pass dummy connection string to it. You cannot pass empty one, so use some parameters there
var ctx = (DbContext) constructor.Invoke(new object[] {"App=EntityFramework"});
try {
var ms = new MemoryStream();
var writer = new XmlTextWriter(ms, Encoding.UTF8);
// here is first catch - generate edmx file yourself and save to xml document
EdmxWriter.WriteEdmx(ctx, writer);
ms.Seek(0, SeekOrigin.Begin);
var rawEdmx = XDocument.Load(ms);
// now we are crude-parsing edmx to get to the elements we need
var runtime = rawEdmx.Root.Elements().First(c => c.Name.LocalName == "Runtime");
var cModel = runtime.Elements().First(c => c.Name.LocalName == "ConceptualModels").Elements().First();
var sModel = runtime.Elements().First(c => c.Name.LocalName == "StorageModels").Elements().First();
var mModel = runtime.Elements().First(c => c.Name.LocalName == "Mappings").Elements().First();

// now we build a list of stuff needed for constructor of MetadataWorkspace
var cItems = new EdmItemCollection(new[] {XmlReader.Create(new StringReader(cModel.ToString()))});
var sItems = new StoreItemCollection(new[] {XmlReader.Create(new StringReader(sModel.ToString()))});
var mItems = new StorageMappingItemCollection(cItems, sItems, new[] {XmlReader.Create(new StringReader(mModel.ToString()))});
// and done
return new MetadataWorkspace(() => cItems, () => sItems, () => mItems);
}
finally {
ctx.Dispose();
}
}

关于c# - 是否可以在不连接数据库的情况下检索 MetadataWorkspace?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28703410/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com