Avatar billede Droa Seniormester
06. juni 2017 - 22:32 Der er 4 kommentarer

EntityFramework Core en til mange

Hej Eksperter

Jeg er igang med og prøve det nye EntityFramework Core (tidligere kaldt 7.0)

Hvor jeg har brug for en HasOne().WithMany() og dens reverse HasOne().WithMany()


det handler om mine Set som ser sådan her ud.
Account.cs

public class Account
    {
        [Key,DatabaseGenerated(DatabaseGeneratedOption.Identity)]public int AccountId { get; set; }
        public string Email { get; set; }
        public byte[] PasswordSha1 { get; set; }
        public byte[] Salt { get; set; }
        public virtual List<Activation> Activations { get; set; } = new List<Activation>();
    }


Activation.cs

    public class Activation
    {
        [Key,DatabaseGenerated(DatabaseGeneratedOption.Identity)]public int ActivationId { get; set; }
        public int AccountId { get; set; }
        public string ActivationCode { get; set; }
        public DateTime? Validated { get; set; }
        public DateTime Created { get; set; } = DateTime.UtcNow;
        public Account Account { get; set; }
        public string Status { get; set; }
    }


min ContextDB ser sådan her ud.


    public class AccountsContext : DbContext
    {
        static RandomNumberGenerator Random = RandomNumberGenerator.Create();
        public DbSet<Account> Accounts { get; set; }
        public DbSet<Activation> Activations { get; set; }

        public AccountsContext(DbContextOptions<AccountsContext> options) : base(options)
        {

        }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            builder.Entity<Account>()
                .HasIndex(u => u.Email)
                .IsUnique();
            builder.Entity<Account>()
                .HasMany(account => account.Activations)
                .WithOne(activation => activation.Account);
            builder.Entity<Activation>()
                .HasOne(activation => activation.Account)
                .WithMany(account => account.Activations);
        }
}


Jeg kan let nok bruge Accounts.Where(a => a.AccountId == 1).FirstOrDefault().Activations

men når jeg prøver og bruge Activations-Where(a => a.Account.AccountId == 1).FirstOrDefault().Activations

giver den null i Activation->Account objektet.

jeg ved godt at sætningerne ikke giver mening, men er kun et eksempel.

hvorfor er Account Null i Activations? databasen er sat op korrekt,

Activations entity bruger AccountId til og finde Accounts entity

Accounts key er AccountId

Activations key er ActivationId

på forhånd tak :)
Avatar billede arne_v Ekspert
07. juni 2017 - 04:08 #1
Hvis databasen er korrekt sat op (med foreign keys)  var det saa ikke nemmere med database first fremfor code first?
Avatar billede arne_v Ekspert
07. juni 2017 - 04:12 #2
Jeg forstaa ikke:

    public class Activation
    {
        ...
        public int AccountId { get; set; }
        ...
        public Account Account { get; set; }
        ...
    }

Det giver ingen mening at have baade AccountID og Account i Activation.
Avatar billede Droa Seniormester
07. juni 2017 - 12:00 #3
Account kan have flere Activations

Så jeg har AccountId i Activations, så de ved hvad Account de høre til

Så når man vil finde alle Activations til een Account, skal ens SQL se ud som nogen lignene.

<div>
SELECT ActivationId,ActivationCode,Status FROM Nerd.Activations as t1
Left Join Nerd.Accounts as t2 ON t1.AccountId = t2.AccountId
Where t2.Email = 'user@domain.tld'
</div>

Som betyder jeg bruger Accounts til og lave Email om til AccountId, som Activations bruger til og refererer til en bruger.

Håber det giver bedre mening
Avatar billede Droa Seniormester
12. juni 2017 - 23:28 #4
jeg tror jeg har fundet ud af problemet, det virker til at EntityFramework Core ikke henter reference Sets automatisk, så jeg skal loade alle linkede DbSets før den laver referencer.



List<Account> Account = _accountContext.Accounts.Where(a => a.AccountId == AccountId).ToList();
                List<Activation> activations = _accountContext.Activations.Where(acti => acti.AccountId == AccountId).ToList();


når de så er loadet i ens Context vil de automatisk bruges.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester