0

私のアプリケーションは .NET 4.5 を対象としており、EntityFramework 5.0、Sql Server Compact 4.0 を使用しています。

データベースにいくつかのエンティティをシードしようとしていますが、スローし続けます:

「System.Data.SqlServerCe.SqlCeException: 対応する主キー値が存在しないため、外部キー値を挿入できません。[外部キー制約名 = FK_dbo.User_dbo.Account_AccountKey ]」

以下は、私のドメイン エンティティの簡易版です。

public class Account
{
    public int AccountKey { get; set; }
    public string Name { get; set; }

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

internal class AccountMap : EntityTypeConfiguration<Account>
{
    public AccountMap()
    {
        this.HasKey(e => e.AccountKey);
        this.Property(e => e.AccountKey).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        this.Property(e => e.Name).IsRequired();
    }
}


public class User
{
    public int UserKey { get; set; }
    public string Name { get; set; }

    public Account Account { get; set; }
    public int AccountKey { get; set; }
}

internal class UserMap : EntityTypeConfiguration<User>
{
    public UserMap()
    {
        this.HasKey(e => e.UserKey);
        this.Property(e => e.UserKey).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        this.Property(e => e.Name).IsRequired();


        this.HasRequired(e => e.Account)
            .WithMany(e => e.Users)
            .HasForeignKey(e => e.AccountKey);
    }
}

public class TestContext : DbContext
{
    public TestContext()
    {
        this.Configuration.LazyLoadingEnabled = false;
    }

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

    public DbSet<Account> Accounts { get; set; }



    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); modelBuilder.Conventions.Remove<StoreGeneratedIdentityKeyConvention>();

        modelBuilder.LoadConfigurations();
    }

}

接続文字列:

<connectionStrings>
    <add name="TestContext" connectionString="Data Source=|DataDirectory|\TestDb.sdf;" providerName="System.Data.SqlServerCe.4.0" />
  </connectionStrings>

この問題を示すサンプル アプリケーションを次に示します。

class Program
{
    static void Main(string[] args)
    {
        try
        {
            Database.SetInitializer(new DropCreateDatabaseIfModelChanges<TestContext>());
            using (var context = new TestContext())
                context.Database.Initialize(false);

            for (int i = 0; i < 2; i++ )
                using (var context = new TestContext())
                {
                    var account1 = new Account()
                    {
                        Name = "Account1"
                    };

                    var user1 = new User()
                    {
                        Name = "User1",
                        Account = account1
                    };

                    context.Accounts.AddOrUpdate(
                        e => e.Name,
                        account1
                    );

                    context.Users.AddOrUpdate(
                        e => e.Name,
                        user1
                    );

                    context.SaveChanges();

                    Console.WriteLine("\nChanges saved.");
                }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }

        Console.WriteLine("\nPress any key to exit...");
        Console.ReadLine();
    }
}

Account クラスは、User クラスと 1 対多の関係にあります。私のシード メソッドは、デフォルトのユーザーでデフォルトのアカウントを初期化しようとします。これは AddOrUpdate メソッドの一般的な使用方法だと思われるかもしれませんが、この場合は機能しないようです。ユーザーなしで同じアカウントを 2 回追加すると、問題なく動作します。

誰が私が欠けている点を見ることができますか?

この単純な関係に何か問題がありますか?

AddOrUpdate メソッドは、このような状況で機能するように設計されていますか?

そうでない場合、その種のシードを達成するための正しいアプローチは何でしょうか?

4

2 に答える 2

0

これで軌道に乗るはずです:

using (var context = new TestContext())
{
    // with 1:many we don't need to specify PK when seeding, EF will pick this up
    var accounts = new List<Account>
    {
        // new a list of type User for each account
        new Account() { Name = "Account1", Users = new List<User>() },
        new Account() { Name = "Account2", Users = new List<User>() }
    };
    accounts.ForEach(a => context.Accounts.AddOrUpdate(a));
    context.SaveChanges();

    var users = new List<User>
    {
        // set the account key for each User
        new User() { Name = "User1", AccountKey = 1 },
        new User() { Name = "User2", AccountKey = 1 },
        new User() { Name = "User3", AccountKey = 2 },
        new User() { Name = "User4", AccountKey = 2 }
    };
    users.ForEach(u => context.Users.AddOrUpdate(u));
    context.SaveChanges();

    // add users to list of type user in an account
    accounts[0].Users.Add(users[0]);
    accounts[0].Users.Add(users[1]);
    accounts[1].Users.Add(users[2]);
    accounts[1].Users.Add(users[3]);
    context.SaveChanges();
}

編集

これを行う前に、おそらくデータベースを削除して再作成することをお勧めします。これは、データベースを数回シードし、「ユーザーなしで同じアカウントを 2 回追加する」と、アカウント テーブルに多数の行があり、テーブルに何もないためです。ユーザーテーブル。

次の注釈を に追加することもできますUser.Account

[ForeignKey("AccountKey")]
public Account Account { get; set; }

また、どのナビゲーション プロパティも仮想ではない理由は何ですか?

于 2013-05-14T19:14:13.053 に答える
0

次の変更を加えて動作させました。

var account1 = new Account()
{
    Name = "Account1"
};

var user1 = new User()
{
    Name = "User1",
    //Account = account1
};

account1.Users = new List<User>(new[]{user1});

context.Accounts.AddOrUpdate(
    e => e.Name,
    account1
);

context.SaveChanges();

しかし、なぜそれが機能するのかわかりません。最初の試行は理にかなっており、問題なく動作するはずです。

于 2013-08-12T21:44:39.047 に答える