sql >> Database >  >> RDS >> Oracle

Meerdere databases met licht veranderende modellen. Hoe sta ik toe dat Entity Framework kolommen tijdens runtime verwijdert?

Oké, dus ik heb dit vervelende ding gebouwd waarmee je tijdens runtime kolommen uit tabellen kunt verwijderen.

1.U moet een constructoroverbelasting toevoegen aan uw DbContext (*.edmx ->*.Context.tt ->*.Context.cs ) leuk vinden:

public partial class EcomEntities : DbContext
{
    public EcomEntities(DbConnection connection)
        : base(connection, true)
    {
    }

    public EcomEntities(string connectionString)
        : base(connectionString)
    {
    }

2.Je hebt een databaseverbindingswisselaar nodig (ik ben hier expliciet hardcoded parameters voor de duidelijkheid, normaal zou je ze krijgen van SystemToDatabaseMapping ). ColumnsToRemove heeft tabel- en kolomnamen die verwijderd moeten worden, EF connectionString is zelf verklarend .

public void ChangeConnection(SystemToDatabaseMapping systemToDatabaseMapping)
{  
    if (systemToDatabaseMapping.ColumnsToRemove != null)
        {
            var entityConnection = EntityConnectionExtensions.Create(
                new List<ColumnsToRemove> { new ColumnsToRemove("QUOTE_HOUSE", "UPRN"), new ColumnsToRemove("QUOTE_HOUSE", "INSIGHT_DATA") },
                systemToDatabaseMapping.ConnectionString);
            this.Ecom = new EcomEntities(entityConnection);
        }
        else
        {
            this.Ecom = new EcomEntities(systemToDatabaseMapping.ConnectionString);
        }
 ....
}

En dan de man die echt vervelende dingen doet, zoals het verwijderen van knooppunten uit de XML-bestanden voor het in kaart brengen van entiteiten, voordat ze worden doorgestuurd naar MetadataWorkspace

using System.Collections.Generic;
using System.Data.Common;
using System.Data.Entity.Core.EntityClient;
using System.Data.Entity.Core.Mapping;
using System.Data.Entity.Core.Metadata.Edm;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Linq;

public static class EntityConnectionExtensions
{
    public static IEnumerable<XElement> ElementsAnyNS<T>(this IEnumerable<T> source, string localName)
        where T : XContainer
    {
        return source.Elements().Where(e => e.Name.LocalName == localName);
    }

    public static IEnumerable<XElement> ElementsAnyNS(this XContainer source, string localName)
    {
        return source.Elements().Where(e => e.Name.LocalName == localName);
    }

    private static void RemoveNodes(XElement element, List<ColumnsToRemove> tableAndColumn)
    {
        if (element.Attribute("Name") != null && tableAndColumn.Any(oo => oo.Table == element.Attribute("Name").Value) ||
            element.Attribute("StoreEntitySet") != null && tableAndColumn.Any(oo => oo.Table == element.Attribute("StoreEntitySet").Value))
        {
            var matchingSelectParts = tableAndColumn.Where(oo => element.Value.Contains(string.Format("\"{0}\".\"{1}\" AS \"{1}\"", oo.Table, oo.Column))).ToList();
            if (matchingSelectParts.Any())
            {
                foreach (var matchingSelectPart in matchingSelectParts)
                {
                    var definingQuery = element.ElementsAnyNS("DefiningQuery").Single();
                    definingQuery.Value = definingQuery.Value.Replace(string.Format(", \n\"{0}\".\"{1}\" AS \"{1}\"", matchingSelectPart.Table, matchingSelectPart.Column), "");
                }
            }
            else
            {
                var nodes = element.Nodes()
                    .Where(o =>
                        o is XElement
                        && ((XElement) o).Attribute("Name") != null
                        && tableAndColumn.Any(oo => ((XElement) o).Attribute("Name").Value == oo.Column));
                foreach (var node in nodes.ToList())
                {
                    node.Remove();
                }
            }
        }
    }

    public static EntityConnection Create(List<ColumnsToRemove> tablesAndColumns, string connString)
    {
        var modelNameRegex = new Regex(@".*metadata=res:\/\/\*\/([a-zA-Z.]*).csdl|.*");
        var model = modelNameRegex.Matches(connString).Cast<Match>().SelectMany(o => o.Groups.Cast<Group>().Skip(1).Where(oo => oo.Value != "")).Select(o => o.Value).First();

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

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

        foreach (var entitySet in new[] {storageXml, conceptualXml}.SelectMany(xml => xml.Elements()))
        {
            if (entitySet.Attribute("Name").Value == "ModelStoreContainer")
            {
                foreach (var entityContainerEntitySet in entitySet.Elements())
                {
                    RemoveNodes(entityContainerEntitySet, tablesAndColumns);
                }
            }

            RemoveNodes(entitySet, tablesAndColumns);
        }

        foreach (var entitySet in mappingXml.Elements().ElementAt(0).Elements())
        {
            if (entitySet.Name.LocalName == "EntitySetMapping")
            {
                foreach (var entityContainerEntitySet in entitySet.Elements().First().Elements())
                {
                    RemoveNodes(entityContainerEntitySet, tablesAndColumns);
                }
            }

            RemoveNodes(entitySet, tablesAndColumns);
        }

        var storageCollection = new StoreItemCollection(new [] {storageXml.CreateReader()});
        var conceptualCollection = new EdmItemCollection(new[] { conceptualXml.CreateReader() });
        var mappingCollection = new StorageMappingItemCollection(conceptualCollection, storageCollection, new[] {mappingXml.CreateReader()});

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

public class ColumnsToRemove
{
    public ColumnsToRemove(string table, string column)
    {
        Table = table;
        Column = column;
    }

    public string Table { get; set; }
    public string Column { get; set; }
}

public class SystemToDatabaseMapping
{
    public string ConnectionString { get; set; }
    public List<ColumnsToRemove> ColumnsToRemove  { get; set; }
}

Ik hoop dat dit je wat tijd bespaart.




  1. Hoe MariaDB 10 op RHEL 8 te installeren

  2. Laravel Welsprekend met twee "WHERE NOT IN" in subquery

  3. org.json.JSONException:waarde <br van het type java.lang.String kan niet worden geconverteerd naar JSONObject

  4. Een record scheiden om het bedrag te krijgen