Как я могу создать MetadataWorkspace, используя делегатов загрузки метаданных?

Я последовал этому примеру Изменение имени схемы во время выполнения - Entity Framework, где я могу создать новое EntityConnection из MetaDataWorkspace, которое затем использую для создания DbContext с другой схемой, но я получаю предупреждения компилятора о том, что метод RegisterItemCollection устарел, и о «Construct MetadataWorkspace с использованием конструктора, который принимает делегаты загрузки метаданных».

Как мне это сделать? Вот код, который работает, но дает 3 предупреждения для вызовов RegsiterItemCollection. Я удивлен, что это работает, поскольку предупреждение говорит о том, что устарело, а не просто устарело.

        public static EntityConnection CreateEntityConnection(string schema, string connString, string model)
    {
        XmlReader[] conceptualReader = new XmlReader[]
        {
            XmlReader.Create(
                Assembly
                    .GetExecutingAssembly()
                    .GetManifestResourceStream(model + ".csdl")
            )
        };

        XmlReader[] mappingReader = new XmlReader[]
        {
            XmlReader.Create(
                Assembly
                    .GetExecutingAssembly()
                    .GetManifestResourceStream(model + ".msl")
            )
        };

        var storageReader = XmlReader.Create(
            Assembly
                .GetExecutingAssembly()
                .GetManifestResourceStream(model + ".ssdl")
        );
        //XNamespace storageNS = "http://schemas.microsoft.com/ado/2009/02/edm/ssdl"; // this would not work!!!
        XNamespace storageNS = "http://schemas.microsoft.com/ado/2009/11/edm/ssdl";

        var storageXml = XElement.Load(storageReader);

        foreach (var entitySet in storageXml.Descendants(storageNS + "EntitySet"))
        {
            var schemaAttribute = entitySet.Attributes("Schema").FirstOrDefault();
            if (schemaAttribute != null)
            {
                schemaAttribute.SetValue(schema);
            }
        }
        storageXml.CreateReader();

        StoreItemCollection storageCollection =
            new StoreItemCollection(
                new XmlReader[] { storageXml.CreateReader() }
            );
        EdmItemCollection conceptualCollection = new EdmItemCollection(conceptualReader);
        StorageMappingItemCollection mappingCollection =
            new StorageMappingItemCollection(
                conceptualCollection, storageCollection, mappingReader
            );

        //var workspace2 = new MetadataWorkspace(conceptualCollection, storageCollection, mappingCollection);
        var workspace = new MetadataWorkspace();
        workspace.RegisterItemCollection(conceptualCollection);
        workspace.RegisterItemCollection(storageCollection);
        workspace.RegisterItemCollection(mappingCollection);

        var connectionData = new EntityConnectionStringBuilder(connString);
        var connection = DbProviderFactories
            .GetFactory(connectionData.Provider)
            .CreateConnection();
        connection.ConnectionString = connectionData.ProviderConnectionString;

        return new EntityConnection(workspace, connection);
    }

person Dave    schedule 15.07.2014    source источник
comment
У кого-нибудь есть идеи? Это работает так же, как и у меня, но я хотел бы исправить это, а также избавиться от 3 предупреждений. Предупреждение 1 «System.Data.Entity.Core.Metadata.Edm.MetadataWorkspace.RegisterItemCollection (System.Data.Entity.Core.Metadata.Edm.ItemCollection)» устарело: «Создайте MetadataWorkspace, используя конструктор, который принимает делегатов загрузки метаданных».   -  person Dave    schedule 19.08.2014


Ответы (2)


Мне удалось избавиться от 3 предупреждающих сообщений. В основном он хочет, чтобы вы зарегистрировали коллекции в конструкторе MetadataWorkspace.

Для MetadataWorkspace есть 3 разных перегрузки, я решил использовать ту, которая требует указать путь (массив строк) к метаданным рабочей области. Для этого я сохранил читателей во временные файлы и перезагрузил их.

У меня это работает без каких-либо предупреждений.

public static EntityConnection CreateEntityConnection(string schema, string connString, string model) {

        var conceptualReader = XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream(model + ".csdl"));
        var mappingReader = XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream(model + ".msl"));
        var storageReader = XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream(model + ".ssdl"));

        XNamespace storageNS = "http://schemas.microsoft.com/ado/2009/11/edm/ssdl";

        var storageXml = XElement.Load(storageReader);
        var conceptualXml = XElement.Load(conceptualReader);
        var mappingXml = XElement.Load(mappingReader);

        foreach (var entitySet in storageXml.Descendants(storageNS + "EntitySet")) {
            var schemaAttribute = entitySet.Attributes("Schema").FirstOrDefault();
            if (schemaAttribute != null) {
                schemaAttribute.SetValue(schema);
            }
        }

        storageXml.Save("temp.ssdl");
        conceptualXml.Save("temp.csdl");
        mappingXml.Save("temp.msl");

        MetadataWorkspace workspace = new MetadataWorkspace(new List<String>(){
                                                                @"temp.csdl",
                                                                @"temp.ssdl",
                                                                @"temp.msl"
                                                        } 
                                                       ,  new List<Assembly>());


        var connectionData = new EntityConnectionStringBuilder(connString);
        var connection = DbProviderFactories.GetFactory(connectionData.Provider).CreateConnection();
        connection.ConnectionString = connectionData.ProviderConnectionString;

        return new EntityConnection(workspace, connection);

    }
person Andrew Crouse    schedule 26.09.2014
comment
Потрясающий. Спасибо, Эндрю. Отправлю обратно, если возникнут проблемы. - person Dave; 26.09.2014

Не желая создавать временные файлы, которые замедляют процесс, я обнаружил, что альтернативный ответ на этот вопрос довольно прост. Я заменил эти строки кода -

    //var workspace2 = new MetadataWorkspace(conceptualCollection, storageCollection, mappingCollection);
    var workspace = new MetadataWorkspace();
    workspace.RegisterItemCollection(conceptualCollection);
    workspace.RegisterItemCollection(storageCollection);
    workspace.RegisterItemCollection(mappingCollection);

с этой одной строкой кода -

    var workspace = new MetadataWorkspace(() => conceptualCollection, () => storageCollection, () => mappingCollection);

и это прекрасно работает.

person Dave    schedule 27.10.2014