sql >> データベース >  >> RDS >> Oracle

モデルがわずかに変更された複数のデータベース。 Entity Frameworkが実行時に列を削除できるようにするにはどうすればよいですか?

    さて、実行時にテーブルから列を削除できるこの厄介なものを作成しました。

    1. DbContextにコンストラクターオーバーロードを追加する必要があります (*.edmx ->*.Context.tt ->*.Context.cs )like:

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

    2.データベース接続チェンジャーが必要になります(わかりやすくするために、ここではパラメーターを明示的にハードコーディングしています。通常は、SystemToDatabaseMappingからパラメーターを取得します。 )。 ColumnsToRemove 削除する必要のあるテーブル名と列名があり、EF connectionString は自己です説明

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

    そして、実際に厄介なことをする人は、ノードをMetadataWorkspaceにフィードする前に、エンティティマッピングxmlからノードを削除します。

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

    これで時間を節約できれば幸いです。




    1. デフォルトの権限が原因でPostgreSQLのドロップロールが失敗する

    2. doctrine:build-テーブル列を無視するスキーマ

    3. SQLINステートメント-結果を返すときに重複を保持する

    4. PythonリストからPostgreSQL配列へ