1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

プロパティとしてのクラス(Table Per Type編) 2

Posted at

前回からの考え直し(インターフェイスから抽象型)

前回ではDataTime型に限ったプロパティクラスを考えたが実際の運用考えると下記のような抽象ジェネリッククラスの方が運用しやすい。

CompornentEFcore.cs
    public abstract class CompornentClass<TEntity, DataType> where TEntity : class where DataType : struct
    {
        public CompornentClass() { value = default(DataType); }
        public CompornentClass(DataType value) { this.value = value; }
        public int iD { get; set; }
        public DataType value { get; set; }
        public TEntity CompornentSideNavigation { get; set; }
    }

何故インターフェイスから抽象ジェネリッククラスに置き換えたかというと、そもそもEntityFrameworkは1クラス、1テーブルなので1ジェネリッククラスで複数テーブルは無理あったためである。
実際運用する際にはここから継承して色々機能を加えていくことになる。

コンテキスト定義

さらに似たような型であるからコンテキスト定義も一括できるはずである。
そこでコンポジット側とコンポーネント側の定義を行う静的関数を定義する

ContextUtility.CompositeSide
        public static EntityTypeBuilder<TEntity> ConfigureCopositeSide<TEntity, TRelated, DataType>(
                        this EntityTypeBuilder<TEntity> EntityTypeBuilder,
            Expression<Func<TEntity, TRelated>> ConpositeSideProperty
            )
                        where TEntity : class where TRelated : CompornentClass<TEntity, DataType> where DataType : struct
        {
            EntityTypeBuilder.Navigation(ConpositeSideProperty);
            EntityTypeBuilder.HasOne(ConpositeSideProperty)
                .WithOne(CompornentClass => CompornentClass.CompornentSideNavigation);
            return EntityTypeBuilder;
        }

この関数で行っていることは
入力としてエンティティタイプビルダー、コンポジット側プロパティを受け取って
ナビゲーションプロパティとしてコンポーネント側を返す関数を定義して
ナビゲーションプロパティから1対1で関係性を定義している。
ジェネリックの型情報が3つに成っているが恐らくは型推定で補完されるだろう。

ContextUtility.CompornentSide
        public static EntityTypeBuilder<TRelated> ConfigureCompornentSide<TEntity, TRelated, DataType>(
            this EntityTypeBuilder<TRelated> EntityTypeBuilder,
            Expression<Func<TEntity, object>> ConpositeSideID,
            Expression<Func<TEntity, TRelated>> ConpositeSideProperty)
            where TEntity : class where TRelated : CompornentClass<TEntity, DataType> where DataType : struct
        {
            EntityTypeBuilder.ToTable(typeof(TEntity).ToString() + '_' + ConpositeSideProperty.Type.ToString() + "_Values");
            EntityTypeBuilder.HasKey(d => d.iD);
            EntityTypeBuilder.Property(d => d.value).IsRequired();
            EntityTypeBuilder.Navigation(d => d.CompornentSideNavigation);
            EntityTypeBuilder.HasOne(d => d.CompornentSideNavigation)
                .WithOne(ConpositeSideProperty)
                   .HasForeignKey(ConpositeSideID);
            return EntityTypeBuilder;
        }

こちらも同様である。
入力としてエンティティタイプビルダー、コンポジット側ID、コンポジット側プロパティを受け取って
主キー、プロパティ、ナビゲーション、1対1の関係性を定義しているだけである。

今回の成果はGithubで公開中
https://github.com/Nishiwaki-Takao/CompornentEFcore

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?