2013-03-18 16 views
31

2 sınıfım var: İstemci ve Anket.Varlık Çerçeve Kodu İlk: Bir "Varsayılan" değer için yabancı bir tuşa nasıl açıklama eklenir?

Her İstemci birçok ankete sahip olabilir - ancak yalnızca bir tane varsayılan anket.

[dbo].[Clients] 
(
[ID] [int] IDENTITY(1,1) NOT NULL, 
[ClientName] [nvarchar](max) NULL, 
[DefaultSurveyID] [int] NULL 
) 

Ama Anketi tablo ekstra yabancı anahtar vardır: Ben beklediğiniz gibi

public class Client 
{ 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int ID { get; set; } 

    public string ClientName { get; set; } 

    public Nullable<int> DefaultSurveyID { get; set; } 

    [ForeignKey("DefaultSurveyID")] 
    public virtual Survey DefaultSurvey { get; set; } 

    public virtual ICollection<Survey> Surveys { get; set; } 
} 

public class Survey 
{ 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int ID { get; set; } 

    public string SurveyName { get; set; } 

    [Required] 
    public int ClientID { get; set; } 

    [ForeignKey("ClientID")] 
    public virtual Client Client { get; set; } 
} 

Bu istemci tablo oluşturur:

böyle sınıfları tanımladıktan

[dbo].[Surveys] 
(
[ID] [int] IDENTITY(1,1) NOT NULL, 
[SurveyName] [nvarchar](max) NULL, 
[ClientID] [int] NOT NULL, 
[Client_ID] [int] NULL 
) 

Kod İlk olarak neden bu ilişkiyi oluşturuyor ve nasıl yapmam gerektiğini anlatıyorum?

+0

farklı yolları: http://stackoverflow.com/q/5244920/150342 – Colin

cevap

42

sorun olduğunu Birden ilişki içinde oldukları zaman iki varlık arasında, EF Code First hangi navigasyon özelliklerinin eşleştiğini, EF ekstra ilişki o DefaultSurvey mülkiyet Survey sınıfın ID referans olduğunu bilmiyordum çünkü yaratıyordu önceki sürümü ile

public class Client 
{ 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int ID { get; set; } 

    public string ClientName { get; set; } 

    /****Change Nullable<int> by int?, looks better****/ 
    public int? DefaultSurveyID { get; set; } 

    /****You need to add this attribute****/ 
    [InverseProperty("ID")] 
    [ForeignKey("DefaultSurveyID")] 
    public virtual Survey DefaultSurvey { get; set; } 

    public virtual ICollection<Survey> Surveys { get; set; } 
} 

ama: az, buradan kodudur, nasıl anlatmak InverseProperty özniteliğini ekleyerek, Survey numaralı özelliğin parametresinin eklenmesiyle, DefaultSurvey ile eşleşmesi gerektiğini bildirebilirsiniz.

+0

Bir müşterinin çok sayıda anketi olabilir, ancak yalnızca bir tane varsayılan anket olabilir ve bu anket ilk ilişkiyle tanımlanan anketler grubunda olmalıdır. – Colin

+0

@Colin: Üzgünüm, kötüyüm, yazım hatasıydı, ilişkiler bire çok **, cevabımı düzelttim. Gönderdiğim kodu dene ve cevapla. – ecampver

+0

Bir anket, birçok müşteri için varsayılan anket olamaz çünkü anket yalnızca bir müşteriye bağlanabilir.Bu nedenle, Anketler sınıfı bir ClientsDefault koleksiyonu içermemelidir – Colin

2

Entity Framework, tam olarak ne söyleneceğini yapar. Söyledikleriniz, Müşteriler ve Anketler arasında bire-bir ve bire bir ilişki olduğu. İstediğiniz ilişkilerin her ikisini de eşleştirmek için Anket tablosundaki FK'leri oluşturdu. İki ilişkiyi birbirine bağlamaya çalıştığınız konusunda hiçbir fikriniz yok, bence bununla başa çıkabilme yeteneği var mıdır.

Alternatif olarak, Anket nesnesine IsDefaultSurvey alanı eklemeyi düşünebilirsiniz, böylece varsayılan anketi Müşteri nesnesinde sahip olduğunuz Surveys koleksiyonu aracılığıyla sorgulayabilirsiniz. aşağıdaki gibi Hatta, diğer kodun herhangi değiştirmek zorunda bir adım daha ileri gitmek ve hala doğru bakış elde Client.DefaultSurvey kullanabilir böylece istemci nesne üzerinde bir NotMapped özelliği olarak bunu koymak ve olamazdı:

[NotMapped] 
public Survey DefaultSurvey 
{ 
    get { return this.Surveys.First(s => s.IsDefaultSurvey); } 
} 
+0

Bu güzel bir numara, ama ayar öyle değil o kolay? – Colin

+0

Bir şekilde veritabanına varsayılan anketin hangisi olduğunu söylemelisiniz. Bunu, anketin düzenleme sayfasının bir parçası olarak yapabilir ve ardından, istemciye yalnızca bir tane varsayılan anket olduğundan emin olmak için doğrulama yapabilirdiniz. – IronMan84

+0

Bunu tam olarak anlamadım. Müşteri ve ClientID özelliklerini Survey sınıfına koyarak bire çok belirttim. DefaultSurvey ve DefaultSurveyID'yi Client sınıfına koyarak bire bir belirttim - ama bire bir olduğunu söyleyecek bir şey yok mu? Şaşkın .... – Colin

11

Sen :-)

1) SMS

kullanarak veritabanında yukarıdaki gibi) ekstra CLIENT_ID olmadan (tablo ve ilişkileri oluşturulan hile bir kod birinci uzmanı kod ilk kullanan, ancak olmamak yapabiliriz

2) Gerekli sınıfları ve eşlemeleri oluşturmak için Reverse Engineer Code First kullandım

3) Veritabanını bıraktım ve context.Database kullanarak yeniden oluşturdum.Create()

Orjinal tablo defs:

CREATE TABLE [dbo].[Client](
    [Id] [int] IDENTITY(1,1) NOT NULL, 
    [Name] [nvarchar](50) NULL, 
    [DefaultSurveyId] [int] NULL, 
    CONSTRAINT [PK_dbo.Client] PRIMARY KEY NONCLUSTERED 
    (
     [Id] ASC 
    ) 
) 

CREATE TABLE [dbo].[Survey](
    [Id] [int] IDENTITY(1,1) NOT NULL, 
    [Name] [nvarchar](50) NULL, 
    [ClientId] [int] NULL, 
    CONSTRAINT [PK_dbo.Survey] PRIMARY KEY NONCLUSTERED 
    (
     [Id] ASC 
    ) 
) 

Artı ters mühendislik tarafından oluşturulan yabancı anahtarlar

ALTER TABLE [dbo].[Survey] WITH CHECK 
    ADD CONSTRAINT [FK_dbo.Survey_dbo.Client_ClientId] FOREIGN KEY([ClientId]) 
    REFERENCES [dbo].[Client] ([Id]) 

ALTER TABLE [dbo].[Client] WITH CHECK 
    ADD CONSTRAINT [FK_dbo.Client_dbo.Survey_DefaultSurveyId] 
    FOREIGN KEY([DefaultSurveyId]) REFERENCES [dbo].[Survey] ([Id]) 

Kodu:

public partial class Client 
{ 
    public Client() 
    { 
     this.Surveys = new List<Survey>(); 
    } 

    public int Id { get; set; } 
    public string Name { get; set; } 
    public int? DefaultSurveyId { get; set; } 
    public virtual Survey DefaultSurvey { get; set; } 
    public virtual ICollection<Survey> Surveys { get; set; } 
} 

public partial class Survey 
{ 
    public Survey() 
    { 
     this.Clients = new List<Client>(); 
    } 

    public int Id { get; set; } 
    public string Name { get; set; } 
    public int? ClientId { get; set; } 
    public virtual ICollection<Client> Clients { get; set; } 
    public virtual Client Client { get; set; } 
} 

public class ClientMap : EntityTypeConfiguration<Client> 
{ 
    #region Constructors and Destructors 

    public ClientMap() 
    { 
     // Primary Key 
     this.HasKey(t => t.Id); 

     // Properties 
     this.Property(t => t.Name).HasMaxLength(50); 

     // Table & Column Mappings 
     this.ToTable("Client"); 
     this.Property(t => t.Id).HasColumnName("Id"); 
     this.Property(t => t.Name).HasColumnName("Name"); 
     this.Property(t => t.DefaultSurveyId).HasColumnName("DefaultSurveyId"); 

     // Relationships 
     this.HasOptional(t => t.DefaultSurvey) 
      .WithMany(t => t.Clients).HasForeignKey(d => d.DefaultSurveyId); 
    } 

    #endregion 
} 

public class SurveyMap : EntityTypeConfiguration<Survey> 
{ 
    #region Constructors and Destructors 

    public SurveyMap() 
    { 
     // Primary Key 
     this.HasKey(t => t.Id); 

     // Properties 
     this.Property(t => t.Name).HasMaxLength(50); 

     // Table & Column Mappings 
     this.ToTable("Survey"); 
     this.Property(t => t.Id).HasColumnName("Id"); 
     this.Property(t => t.Name).HasColumnName("Name"); 
     this.Property(t => t.ClientId).HasColumnName("ClientId"); 

     // Relationships 
     this.HasOptional(t => t.Client) 
      .WithMany(t => t.Surveys).HasForeignKey(d => d.ClientId); 
    } 

    #endregion 
} 
+0

'daki seçenekleri anlama konusunda bana yardımcı olan +1, yapabiliyorsanız kodu eklemenin çok yararlı olacağını düşünüyorum. – Colin

+0

Bu, sorunu gidermek için Fluent API'yi kullanan mükemmel bir çözümdür. Entity Framework +1 – Colin

+1

ile neler yapılabileceğini anlamamda bana yardımcı oldu. Bana sadece bağlantıyı veriyor ve bana "EF Güç Araçları" hakkında bilgi vermek, altın ağırlık değerine değdi. Teşekkürler –

1

Lütfen aşağıdaki kodu ekleyerek sorunu çözeceğinizi unutmayın. bir veritabanında bu problem

public class ApplicationDbContext : IdentityDbContext<ApplicationUser> 
{ 
    public ApplicationDbContext() : base("DefaultConnection") 
    { 

    } 
    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
      modelBuilder.Entity<Client>() 
         .HasOptional(x => x.DefaultSurvey) 
         .WithMany(x => x.Surveys); 
         .HasForeignKey(p => p.DefaultSurveyID); 
    { 
} 
İlgili konular