Nazwa pola z kluczem obcym

0

Witam wszystkich i kłaniam się nisko jako że to mój pierwszy post na forum.
Na początek zaznaczam, że jestem bardzo początkujący w temacie dlatego proszę o wyrozumiałość.
Piszę programik z EF6 Code First. Mam Dwie klasy DictionaryMaster i DictionarySlave. Jak się można domyśleć są powiązane relacją 1+M. Ppotrzebuję ustawić konkretną moją nazwę pola obsługującego relacje. O co dokładnie chodzi wyjaśniam w dalszej części.

Klasy wyglądają następująco

namespace sopd2.Models
{
    using RichardLawley.EF.AttributeConfig;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;

    [Table("dictionarymaster")]
    public class DictionaryMaster
    {
        [Key]
        public int ID { get; set; }

        [Column("DM_KEY", TypeName="char")]
        [Index("IX_Key"),StringLength(10)]
        public string DictMasterKey { get; set; }

        [Column("DM_DESCRIPTION", TypeName = "nvarchar")]
        [Index("IX_Description"), StringLength(50)]
        public string DictMasterDescription { get; set; }

        [Column("DM_VALUE1")]
        [DecimalPrecision(11, 2)]
        public decimal? DictMasterValue1 { get; set; }

        [Column("DM_VALUE2")]
        [DecimalPrecision(11, 2)]
        public decimal? DictMasterValue2 { get; set; }

        public ICollection<DictionarySlave> DictionarySlaves { get; set; }

    }

    [Table("dictionaryslave")]
    public partial class DictionarySlave
    {
        [Key]
        public int ID { get; set; }

        [Column("DS_KEY", TypeName = "char")]
        [Index("IX_Key"), StringLength(10)]
        public string DictSlaveKey { get; set; }

        [Column("DS_DESCRIPTION", TypeName = "nvarchar")]
        [Index("IX_Description"), StringLength(50)]
        public string DictSlaveDescription { get; set; }

        [Column("DS_VALUE1")]
        [DecimalPrecision(11, 2)]
        public decimal? DictSlaveValue1 { get; set; }

        [Column("DS_VALUE2")]
        [DecimalPrecision(11, 2)]
        public decimal? DictSlaveValue2 { get; set; }

    }
}

Migracja tworzy mi następujący kod tworzący tabele

namespace sopd2.Migrations
{
    using System;
    using System.Data.Entity.Migrations;
    
    public partial class des01 : DbMigration
    {
        public override void Up()
        {           
            CreateTable(
                "dbo.dictionarymaster",
                c => new
                    {
                        ID = c.Int(nullable: false, identity: true),
                        DM_KEY = c.String(maxLength: 10, fixedLength: true, unicode: false, storeType: "char"),
                        DM_DESCRIPTION = c.String(maxLength: 50, storeType: "nvarchar"),
                        DM_VALUE1 = c.Decimal(precision: 11, scale: 2),
                        DM_VALUE2 = c.Decimal(precision: 11, scale: 2),
                    })
                .PrimaryKey(t => t.ID)
                .Index(t => t.DM_KEY, name: "IX_Key")
                .Index(t => t.DM_DESCRIPTION, name: "IX_Description");
            
            CreateTable(
                "dbo.dictionaryslave",
                c => new
                    {
                        ID = c.Int(nullable: false, identity: true),
                        DS_KEY = c.String(maxLength: 10, fixedLength: true, unicode: false, storeType: "char"),
                        DS_DESCRIPTION = c.String(maxLength: 50, storeType: "nvarchar"),
                        DS_VALUE1 = c.Decimal(precision: 11, scale: 2),
                        DS_VALUE2 = c.Decimal(precision: 11, scale: 2),
                        DictionaryMaster_ID = c.Int(),
                    })
                .PrimaryKey(t => t.ID)
                .ForeignKey("dbo.dictionarymaster", t => t.DictionaryMaster_ID)
                .Index(t => t.DS_KEY, name: "IX_Key")
                .Index(t => t.DS_DESCRIPTION, name: "IX_Description")
                .Index(t => t.DictionaryMaster_ID);
            
        }
        
        public override void Down()
        {
            DropIndex("dbo.dictionaryslave", new[] { "DictionaryMaster_ID" });
            DropIndex("dbo.dictionaryslave", "IX_Description");
            DropIndex("dbo.dictionaryslave", "IX_Key");
            DropIndex("dbo.dictionarymaster", "IX_Description");
            DropIndex("dbo.dictionarymaster", "IX_Key");
        }
    }
}

Jak widać w tabeli 'dictionaryslave' niejako od zaplecza zostało stworzone pole 'DictionaryMaster_ID' jako klucz obcy do obsługi relacji 1+M. Widać również że jego nazwa nie pasuje do przyjętej konwencji nazewnictwa kolumn w tabeli. Chciałbym je ustawić na 'DS_DMID'. Próbowałem zdefiniować kolejną właściwość w klasie DictionarySlave ale nie udało mi się jej podpiąć jako ForeinKey

[ForeignKey("DS_DMID")]
        public int DictMasterID { get; set; }

Mam inny zestaw klas z relacją M+N i poradziłem sobie z podobnym tematem następująco :

[Table("users")]
    public partial class User
    {
        [Key]
        public int ID { get; set; }

        [Column("US_LOGIN", TypeName = "char")]
        [Required]
        [StringLength(10)]
        public string Login { get; set; }

        [Column("US_NAME",TypeName = "nvarchar")]
        [Required]
        [StringLength(30)]
        public string SurName { get; set; }

        [Column("US_FNAME", TypeName = "nvarchar")]
        [Required]
        [StringLength(30)]
        public string FirstName { get; set; }

        [Column("US_EMAIL", TypeName = "nvarchar")]
        [Required]
        [StringLength(30)]
        public string Email { get; set; }

        [Column("US_TIMESTAMP")]
        public DateTime? TimeStamp { get; set; }

        [Column("US_PRIVILEGE", TypeName = "bigint")]
        public long Privilege { get; set; }

        [Column("US_HASH", TypeName = "char")]
        [StringLength(50)]
        public string Hash { get; set; }

        public virtual ICollection<UserGroup> UserGroups { get; set; }
    }

    [Table("usergroups")]
    public partial class UserGroup
    {
        [Key]
        public int ID { get; set; }

        [Column("UG_NAME", TypeName = "nvarchar")]
        [Required]
        [Index("IX_Name"), StringLength(50)]
        public string UserGroupName { get; set; }

        public ICollection<User> Users { get; set; }
    }

I w metodzie OnModelCreating coś takiego co załatwia mi zmianę nazwy tabeli jak również własne nazwy kolumn i gitara. Mniej więcej rozumiem co poniższe robi ale niestety nie potrafię poniższego zaimplementować w tabeli podrzędnej DictionarySlave w relacji 1+M.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention>();
            // Add conventions for Precision Attributes
            modelBuilder.Conventions.Add(new DecimalPrecisionAttributeConvention());
            modelBuilder.Conventions.Add(new DateTimePrecisionAttributeConvention());

            modelBuilder.Entity<User>().HasMany(x => x.UserGroups).WithMany(y => y.Users)
                .Map(m => 
                {
                    m.ToTable("usergroupmembers");
                    m.MapLeftKey("GM_USID");
                    m.MapRightKey("GM_GRID");
                });
        }
0

Który parametr w DictionarySlave ma być kluczem obcym? Czy można trochę przerobić Twój kod, bo w przeciwnym razie obawiam się bez FluentApi się nie obędzie.

Tu masz artykuł
http://www.entityframeworktutorial.net/code-first/configure-one-to-many-relationship-in-code-first.aspx

0

No tak właśnie chyba czegoś mi brakuje. Klasa DictionarySlave powinna chyba wyglądać tak:

 namespace sopdmodel.Models
{
    using RichardLawley.EF.AttributeConfig;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;

    [Table("dictionaryslave")]
    public partial class DictionarySlave
    {
        [Key]
        public int Id { get; set; }
        
        [Column("DS_KEY", TypeName = "char")]
        [Index("IX_Key"), StringLength(10)]
        public string DictSlaveKey { get; set; }

        [Column("DS_DESCRIPTION", TypeName = "nvarchar")]
        [Index("IX_Description"), StringLength(50)]
        public string DictSlaveDescription { get; set; }

        [Column("DS_VALUE1")]
        [DecimalPrecision(11, 2)]
        public decimal? DictSlaveValue1 { get; set; }

        [Column("DS_VALUE2")]
        [DecimalPrecision(11, 2)]
        public decimal? DictSlaveValue2 { get; set; }

        [ForeignKey("DictionaryMaster")] //Has to be a property name, not table column name
        [Column("DS_DMID")]
        public int DictionaryMasterId { get; set; }

        public DictionaryMaster DictionaryMaster { get; set; }
    }
}

Wygląda że zadziałało bo mam teraz w migracji to co chciałem. Martwi mnie (być może niesłusznie) zbieżność nazwy klasy DictionaryMaster jako typu właściwości DictionaryMaster w encji DictionarySlave. Czy może to tak zostać? Poniżej to co mi wyskoczyło w migracji

 CreateTable(
                "dbo.dictionarymaster",
                c => new
                    {
                        Id = c.Int(nullable: false, identity: true),
                        DM_KEY = c.String(maxLength: 10, fixedLength: true, unicode: false, storeType: "char"),
                        DM_DESCRIPTION = c.String(maxLength: 50, storeType: "nvarchar"),
                        DM_VALUE1 = c.Decimal(precision: 11, scale: 2),
                        DM_VALUE2 = c.Decimal(precision: 11, scale: 2),
                    })
                .PrimaryKey(t => t.Id)
                .Index(t => t.DM_KEY, name: "IX_Key")
                .Index(t => t.DM_DESCRIPTION, name: "IX_Description");
           
            CreateTable(
                "dbo.dictionaryslave",
                c => new
                    {
                        Id = c.Int(nullable: false, identity: true),
                        DS_KEY = c.String(maxLength: 10, fixedLength: true, unicode: false, storeType: "char"),
                        DS_DESCRIPTION = c.String(maxLength: 50, storeType: "nvarchar"),
                        DS_VALUE1 = c.Decimal(precision: 11, scale: 2),
                        DS_VALUE2 = c.Decimal(precision: 11, scale: 2),
                        DS_DMID = c.Int(nullable: false),
                    })
                .PrimaryKey(t => t.Id)
                .ForeignKey("dbo.dictionarymaster", t => t.DS_DMID, cascadeDelete: true)
                .Index(t => t.DS_KEY, name: "IX_Key")
                .Index(t => t.DS_DESCRIPTION, name: "IX_Description")
                .Index(t => t.DS_DMID);

Coś wydłubałem z FluentAPI i wyszło takie coś

    public class DictionaryMasterMapping : EntityTypeConfiguration<DictionaryMaster>
    {
        public DictionaryMasterMapping()
            : base()
        {
            // Mapping entity to datatable
            this.HasKey(e => e.Id).Property(e => e.Id).HasColumnName("ID");
            this.Property(e => e.DictMasterKey).HasColumnName("DM_KEY");
            this.Property(e => e.DictMasterDescription).HasColumnName("DM_DESCRIPTION");
            this.Property(e => e.DictMasterValue1).HasColumnName("DM_VALUE1");
            this.Property(e => e.DictMasterValue2).HasColumnName("DM_VALUE2");
            // Mapping indexes
            this.Property(e => e.DictMasterKey).HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_Key") { IsUnique = true }));
            this.Property(e => e.DictMasterDescription).HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_Description")));
            // Mapping relations
            this.HasMany(e => e.DictionarySlaves).WithOptional().Map(p => p.MapKey("DS_DMID")).WillCascadeOnDelete();

            this.ToTable("dictionarymaster");
        }
    }
 

Różnica polega chyba na tym, że przy atrybutach relację definiuję w klasie podrzędnej a we FluentAPI mapuję klasę nadrzędną. Które z podejść jest właściwsze, albo może które jest "passe"?

Walki ciąg dalszy, tym razem z FluentAPI. Oczekiwany efekt daje mi taka konstrukcja:

 //    [Table("dictionaryslave")]
    public partial class DictionarySlave
    {
//        [Key]
        public int Id { get; set; }
        
        //[Column("DS_KEY", TypeName = "char")]
        //[Index("IX_Key"), StringLength(10)]
        public string DictSlaveKey { get; set; }

        //[Column("DS_DESCRIPTION", TypeName = "nvarchar")]
        //[Index("IX_Description"), StringLength(50)]
        public string DictSlaveDescription { get; set; }

//        [Column("DS_VALUE1")]
        [DecimalPrecision(11, 2)]
        public decimal? DictSlaveValue1 { get; set; }

//        [Column("DS_VALUE2")]
        [DecimalPrecision(11, 2)]
        public decimal? DictSlaveValue2 { get; set; }

        //[ForeignKey("DictionaryMaster")] //Has to be a property name, not table column name
        //[Column("DS_DMID")]
        public int DS_DMID { get; set; }

        public DictionaryMaster DictionaryMaster { get; set; }
    }

    public class DictionarySlaveMapping : EntityTypeConfiguration<DictionarySlave>
    {
        public DictionarySlaveMapping()
            : base()
        {
            // Mapping entity to datatable
            this.HasKey(e => e.Id).Property(e => e.Id).HasColumnName("ID");
            this.Property(e => e.DictSlaveKey).HasColumnName("DS_KEY");
            this.Property(e => e.DictSlaveDescription).HasColumnName("DS_DESCRIPTION");
            this.Property(e => e.DictSlaveValue1).HasColumnName("DS_VALUE1");
            this.Property(e => e.DictSlaveValue2).HasColumnName("DS_VALUE2");
            // Mapping indexes
            this.Property(e => e.DictSlaveKey).HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_Key") { IsUnique = true }));
            this.Property(e => e.DictSlaveDescription).HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_Description")));
            // Mapping relations
            this.HasRequired<DictionaryMaster>(e => e.DictionaryMaster).WithMany(s => s.DictionarySlaves).HasForeignKey(s => s.DS_DMID).WillCascadeOnDelete();
            //  .Map(p => p.MapKey("DS_DMID")
            this.ToTable("dictionaryslave");
        }
    }

Nie podoba mi się właściwość DS_DMID w klasie. Wolałbym mieć tam pola jak w wersji z atrybutami.
Takie coś

             this.HasRequired<DictionaryMaster>(e => e.DictionaryMaster).WithMany(s => s.DictionarySlaves).HasForeignKey(s => s.DictionaryMasterId).WillCascadeOnDelete();
 

Zmapować na .Map(p => p.MapKey("DS_DMID")

0

Zrobiłbym to tak

namespace sopd2.Models
{
    using RichardLawley.EF.AttributeConfig;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
 
    [Table("dictionarymaster")]
    public class DictionaryMaster
    {
        [Key]
        public int DictionaryMasterID { get; set; }
 
        [Column("DM_KEY", TypeName="char")]
        [Index("IX_Key"),StringLength(10)]
        public string DictMasterKey { get; set; }
 
        [Column("DM_DESCRIPTION", TypeName = "nvarchar")]
        [Index("IX_Description"), StringLength(50)]
        public string DictMasterDescription { get; set; }
 
        [Column("DM_VALUE1")]
        [DecimalPrecision(11, 2)]
        public decimal? DictMasterValue1 { get; set; }
 
        [Column("DM_VALUE2")]
        [DecimalPrecision(11, 2)]
        public decimal? DictMasterValue2 { get; set; }
 
        public virtual ICollection<DictionarySlave> DictionarySlaves { get; set; }
 
    }
 
    [Table("dictionaryslave")]
    public partial class DictionarySlave
    {
        [Key]
        public int DictionarySlaveID { get; set; }

        [....]
        public int DictionaryMasterID { get; set; }
 
        [Column("DS_KEY", TypeName = "char")]
        [Index("IX_Key"), StringLength(10)]
        public string DictSlaveKey { get; set; }
 
        [Column("DS_DESCRIPTION", TypeName = "nvarchar")]
        [Index("IX_Description"), StringLength(50)]
        public string DictSlaveDescription { get; set; }
 
        [Column("DS_VALUE1")]
        [DecimalPrecision(11, 2)]
        public decimal? DictSlaveValue1 { get; set; }
 
        [Column("DS_VALUE2")]
        [DecimalPrecision(11, 2)]
        public decimal? DictSlaveValue2 { get; set; }

        public virtual DictionaryMaster DictionaryMaster { get; set; }
 
    }
} 

I tu jedno "ale" klasa DictionarySlave jest partial, czy w następnych częściach tej klasy coś "zburzy" migrację? Czy nazwy parametrów muszą pozostać bez zmian? Powyższe jest rozwiązanie, gdzie nie trzeba (nie powinieneś) już pisać FuentApi. Sama migracja wystarczy - tak sądzę.

0

Partial wpadło z rozpędu. Na razie nie planuję dzielić klasy na części.
W powyższym brakuje mapowania właściwości DictionaryMasterID w slave na kolumnę DS_DMID a o to mi głównie chodziło. Wczoraj miałem chyba pomroczność jasną i było już za późno żeby to zrobić dobrze. Ostateczna wersja powinna być taka:

 
namespace sopdmodel.Models
{
    using RichardLawley.EF.AttributeConfig;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
 
    [Table("dictionarymaster")]
    public class DictionaryMaster
    {
        [Key]
        [Column("ID")]
        public int Id { get; set; }
 
        [Column("DM_KEY", TypeName="char")]
        [Index("IX_Key", IsUnique = true),StringLength(10)]
        public string DictMasterKey { get; set; }
 
        [Column("DM_DESCRIPTION", TypeName = "nvarchar")]
        [Index("IX_Description"), StringLength(50)]
        public string DictMasterDescription { get; set; }
 
        [Column("DM_VALUE1")]
        [DecimalPrecision(11, 2)]
        public decimal? DictMasterValue1 { get; set; }
 
        [Column("DM_VALUE2")]
        [DecimalPrecision(11, 2)]
        public decimal? DictMasterValue2 { get; set; }
 
        public ICollection<DictionarySlave> DictionarySlaves { get; set; }
 
    }
 
    [Table("dictionaryslave")]
    public class DictionarySlave
    {
        [Key]
        [Column("ID")]
        public int Id { get; set; }
 
        [Column("DS_KEY", TypeName = "char")]
        [Index("IX_Key"), StringLength(10)]
        public string DictSlaveKey { get; set; }
 
        [Column("DS_DESCRIPTION", TypeName = "nvarchar")]
        [Index("IX_Description"), StringLength(50)]
        public string DictSlaveDescription { get; set; }
 
        [Column("DS_VALUE1")]
        [DecimalPrecision(11, 2)]
        public decimal? DictSlaveValue1 { get; set; }
 
        [Column("DS_VALUE2")]
        [DecimalPrecision(11, 2)]
        public decimal? DictSlaveValue2 { get; set; }

        [ForeignKey("DictionaryMaster")]
        [Column("DS_DMID")]
        public int DictionaryMasterID { get; set; }

        public DictionaryMaster DictionaryMaster { get; set; }
    }
} 

daje to migrację :

    public partial class DictMapp : DbMigration
    {
        public override void Up()
        {
            CreateTable(
                "dbo.dictionarymaster",
                c => new
                    {
                        ID = c.Int(nullable: false, identity: true),
                        DM_KEY = c.String(maxLength: 10, fixedLength: true, unicode: false, storeType: "char"),
                        DM_DESCRIPTION = c.String(maxLength: 50, storeType: "nvarchar"),
                        DM_VALUE1 = c.Decimal(precision: 11, scale: 2),
                        DM_VALUE2 = c.Decimal(precision: 11, scale: 2),
                    })
                .PrimaryKey(t => t.ID)
                .Index(t => t.DM_KEY, unique: true, name: "IX_Key")
                .Index(t => t.DM_DESCRIPTION, name: "IX_Description");
            
            CreateTable(
                "dbo.dictionaryslave",
                c => new
                    {
                        ID = c.Int(nullable: false, identity: true),
                        DS_KEY = c.String(maxLength: 10, fixedLength: true, unicode: false, storeType: "char"),
                        DS_DESCRIPTION = c.String(maxLength: 50, storeType: "nvarchar"),
                        DS_VALUE1 = c.Decimal(precision: 11, scale: 2),
                        DS_VALUE2 = c.Decimal(precision: 11, scale: 2),
                        DS_DMID = c.Int(nullable: false),
                    })
                .PrimaryKey(t => t.ID)
                .ForeignKey("dbo.dictionarymaster", t => t.DS_DMID, cascadeDelete: true)
                .Index(t => t.DS_KEY, name: "IX_Key")
                .Index(t => t.DS_DESCRIPTION, name: "IX_Description")
                .Index(t => t.DS_DMID);
            
        }
        
        public override void Down()
        {
            DropForeignKey("dbo.dictionaryslave", "DS_DMID", "dbo.dictionarymaster");
            DropIndex("dbo.dictionaryslave", new[] { "DS_DMID" });
            DropIndex("dbo.dictionaryslave", "IX_Description");
            DropIndex("dbo.dictionaryslave", "IX_Key");
            DropIndex("dbo.dictionarymaster", "IX_Description");
            DropIndex("dbo.dictionarymaster", "IX_Key");
            DropTable("dbo.dictionaryslave");
            DropTable("dbo.dictionarymaster");
        }
    }
 

Jak widać w bazie kolumny są ok i nie ma nadmiarowości.

To samo w FluentAPI

    public class DictionaryMaster
    {
        public int Id { get; set; }

        [StringLength(10)]
        public string DictMasterKey { get; set; }

        [StringLength(50)]
        public string DictMasterDescription { get; set; }

        [DecimalPrecision(11, 2)]
        public decimal? DictMasterValue1 { get; set; }

        [DecimalPrecision(11, 2)]
        public decimal? DictMasterValue2 { get; set; }

        public ICollection<DictionarySlave> DictionarySlaves { get; set; }

    }

    public class DictionaryMasterMapping : EntityTypeConfiguration<DictionaryMaster>
    {
        public DictionaryMasterMapping()
            : base()
        {
            // Mapping entity to datatable
            this.HasKey(e => e.Id).Property(e => e.Id).HasColumnName("ID");
            this.Property(e => e.DictMasterKey).HasColumnName("DM_KEY").HasColumnType("char");
            this.Property(e => e.DictMasterDescription).HasColumnName("DM_DESCRIPTION").HasColumnType("nvarchar");
            this.Property(e => e.DictMasterValue1).HasColumnName("DM_VALUE1");
            this.Property(e => e.DictMasterValue2).HasColumnName("DM_VALUE2");

            // Mapping indexes
            this.Property(e => e.DictMasterKey).HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_Key") { IsUnique = true }));
            this.Property(e => e.DictMasterDescription).HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_Description")));

            // Mapping table
            this.ToTable("dictionarymaster");
        }
    }
    public class DictionarySlave
    {
        public int Id { get; set; }

        [StringLength(10)]
        public string DictSlaveKey { get; set; }

        [StringLength(50)]
        public string DictSlaveDescription { get; set; }

        [DecimalPrecision(11, 2)]
        public decimal? DictSlaveValue1 { get; set; }

        [DecimalPrecision(11, 2)]
        public decimal? DictSlaveValue2 { get; set; }

        public DictionaryMaster DictionaryMaster { get; set; }
    }

    public class DictionarySlaveMapping : EntityTypeConfiguration<DictionarySlave>
    {
        public DictionarySlaveMapping()
            : base()
        {
            // Mapping entity
            this.HasKey(e => e.Id).Property(e => e.Id).HasColumnName("ID");
            this.Property(e => e.DictSlaveKey).HasColumnName("DS_KEY").HasColumnType("char");
            this.Property(e => e.DictSlaveDescription).HasColumnName("DS_DESCRIPTION").HasColumnType("nvarchar");
            this.Property(e => e.DictSlaveValue1).HasColumnName("DS_VALUE1");
            this.Property(e => e.DictSlaveValue2).HasColumnName("DS_VALUE2");

            // Mapping indexes
            this.Property(e => e.DictSlaveKey).HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_Key") { IsUnique = true }));
            this.Property(e => e.DictSlaveDescription).HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_Description")));

            // Mapping relations
            this.HasRequired(e => e.DictionaryMaster).WithMany(s => s.DictionarySlaves).Map(p => p.MapKey("DS_DMID")).WillCascadeOnDelete();

            // Mapping table
            this.ToTable("dictionaryslave");
        }
    }
 

Szybkie ponowione pytanie.
Za i przeciw obu rozwiązań?
Jedno co to przy atrybutach jest mniej pisania.

0

Niech wypowiedzą się tu zawodowcy, nie chce wprowadzać w błąd.
Osobiście preferuje, że jeśli uzyskuje ten sam wynik krótszym kodem to ten kod stosuje i tyle.

0

Zmagań ciąg dalszy. Wymyśliłem sobie, że w DictionarySlave para DictionaryMaster i DictSlaveKey będą stanowiły indeks unikalny. Czyli że w ramach klucza głównego klucze podrzędne muszą być unikalne natomiast klucze podrzędne mogą się powtarzać w różnych kluczach nadrzędnych i nie chodzi tu relację master to slave a o duble kluczy slave z różnymi DS_DMID.
Z atrybutami wygląda to tak:

    [Table("dictionaryslave")]
    public class DictionarySlave
    {
        [Key]
        [Column("ID")]
        public int DictionarySlaveID { get; set; }

        [Column("DS_KEY", TypeName = "char")]
        [Index("IX_Key"), StringLength(10)]
        [Index("IX_DmWithKey", 2, IsUnique = true)]
        public string DictSlaveKey { get; set; }

        [Column("DS_DESCRIPTION", TypeName = "nvarchar")]
        [Index("IX_Description"), StringLength(50)]
        public string DictSlaveDescription { get; set; }

        [Column("DS_VALUE1")]
        [DecimalPrecision(11, 2)]
        public decimal? DictSlaveValue1 { get; set; }

        [Column("DS_VALUE2")]
        [DecimalPrecision(11, 2)]
        public decimal? DictSlaveValue2 { get; set; }

        [ForeignKey("DictionaryMaster")]
        [Column("DS_DMID")]
        [Index("IX_DmWithKey", 1, IsUnique = true)]
        public int DictionaryMasterID { get; set; }

        public DictionaryMaster DictionaryMaster { get; set; }
    } 

i daje to taką migrację :

            CreateTable(
                "dbo.dictionaryslave",
                c => new
                    {
                        ID = c.Int(nullable: false, identity: true),
                        DS_KEY = c.String(maxLength: 10, fixedLength: true, unicode: false, storeType: "char"),
                        DS_DESCRIPTION = c.String(maxLength: 50, storeType: "nvarchar"),
                        DS_VALUE1 = c.Decimal(precision: 11, scale: 2),
                        DS_VALUE2 = c.Decimal(precision: 11, scale: 2),
                        DS_DMID = c.Int(nullable: false),
                    })
                .PrimaryKey(t => t.ID)
                .ForeignKey("dbo.dictionarymaster", t => t.DS_DMID, cascadeDelete: true)
                .Index(t => new { t.DS_DMID, t.DS_KEY }, unique: true, name: "IX_DmWithKey")
                .Index(t => t.DS_KEY, name: "IX_Key")
                .Index(t => t.DS_DESCRIPTION, name: "IX_Description");
 

Czy da się index IX_DmWithKey zrobić we FluentAPI bez tworzenia dodatkowych pól w klasie DictionarySlave? Od biedy mógłby być to klucz główny. Choć jak widać powyżej nie musi.
Oczywiście poniższe nie działa

this.HasKey(e => new { e.DictionaryMaster, e.DictSlaveKey }); 
The property 'DictionaryMaster' cannot be used as a key property on the entity 'sopdmodel.Models.DictionarySlave' because the property type is not a valid key type. Only scalar types, string and byte[] are supported key types.

lub 

this.HasKey(e => new { e.DictionaryMaster.Id, e.DictSlaveKey });
The properties expression 'e => new <>f__AnonymousTypea`2(Id = e.DictionaryMaster.Id, DictSlaveKey = e.DictSlaveKey)' is not valid. The expression should represent a property: C#: 't => t.MyProperty'  VB.Net: 'Function(t) t.MyProperty'. When specifying multiple properties use an anonymous type: C#: 't => new { t.MyProperty1, t.MyProperty2 }'  VB.Net: 'Function(t) New With { t.MyProperty1, t.MyProperty2 }'.

1 użytkowników online, w tym zalogowanych: 0, gości: 1