Evet, bağlamı bir taklit bağlantı dizesi besleyerek bunu yapabilirsiniz. Genellikle, DbContext'in parametresiz yapıcısını çağırdığınızda, ana dizinin app.config dosyasında bağlam sınıfınızın adıyla bağlantı dizesini arayacağını unutmayın. Durum buysa ve bu davranışı değiştiremiyorsanız (söz konusu bağlamın kaynak koduna sahip olmadığınız gibi) - bu aplike bağlantı dizesiyle app.config dosyasını güncellemeniz gerekecektir (çalışma zamanında da yapılabilir). Sonra bağlantı dizesi ile DBContext yapıcısı diyebilirsen:
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);
}
Yani meta çalışma alanını elde etmek için önemli sadece parametrelerin sağlanması ve boş bağlantı dize sağlamaktadır.
GÜNCELLEME: daha fazla düşündükten sonra, bu tür korsanları kullanmanız ve bağlamı başlatmanız gerekmez.
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});
}
Burada sadece incelemek için montaj da o meta elemanlarını hedef yollarının aktarımı, doğrudan MetadataWorkspace sınıfının kurucu ve. Bu yöntemin bazı varsayımlar yaptığına dikkat edin: meta veri yapay kaynaklarının kaynaklara (genellikle bunlar, ancak dışsal veya başka bir yol altında gömülebilir) gömülü olduğu ve gereken her şeyin Bağlam sınıfının kendisi ile aynı mecrada olduğu (teoride olabilirsiniz) Bir mecliste bağlam ve başka bir varlık sınıfı veya bir şey). Ama umarım fikrini alırsın.
UPDATE2: Kod modeli ilkesinde meta veri çalışma alanı almak daha karmaşıktır, çünkü bu model için edmx dosyası çalışma zamanında oluşturulur. Nerede ve nasıl üretildiği, uygulama detaylandırmasıdır. Ancak, bazı çabalarla metadata çalışma alanı elde edebilirsiniz:
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();
}
}
Bağlamı nasıl başlatırsınız? –
@GertArnold Parametre olmayan bir kurucu kullanıyorum – AlexFoxGill