هل يمكن لأي أحد أن يخبرني كيف يمكنني إصلاح النموذج الخاص بي (باستخدام FluentAPI) حتى أتمكن من تعيين مستخدم مختلف إلى User.FriendCollection الخاص بي؟

StackOverflow https://stackoverflow.com//questions/9710655

سؤال

أنا جديد في CodeFirst وأحاول إنشاء مجموعة أصدقاء حتى يتمكن مستخدمان من الحصول على بعضهما البعض في مجموعة الأصدقاء الخاصة بهما.

هنا فئة المستخدم الخاصة بي:

public class User
{
    public User()
    {
        if (FriendCollection == null) FriendCollection = new Collection<Friend>();
    }
    public long ID { get; set; }
    public virtual ICollection<Friend> FriendCollection { get; set; }
}

public class UserConfiguration : EntityTypeConfiguration<User>
{
    public UserConfiguration()
    {
        HasKey(x => x.ID);
    }
}

هنا فئة صديقي:

public class Friend
{
    public Friend()
    {
        DateAdded = DateTime.UtcNow;
    }
    public long ID { get; set; }
    public DateTime DateAdded { get; set; }
    public long UserID { get; set; }
    public virtual User User { get; set; }
}

public class FriendConfiguration : EntityTypeConfiguration<Friend>
{
    public FriendConfiguration()
    {
        HasKey(x => x.ID);
        HasRequired(x => x.User).WithMany(x => x.FriendCollection).HasForeignKey(x => x.UserID);
    }
}

هذه هي فئة الكيان الخاصة بي:

    public Entities()
    {
        Database.SetInitializer<Entities>(new DropCreateDatabaseAlways<Entities>());
    }

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

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new UserConfiguration());
        modelBuilder.Configurations.Add(new FriendConfiguration());

        base.OnModelCreating(modelBuilder);
    }
}

وإليك رمز وحدة التحكم الخاص بي وما أود تحقيقه بشكل مثالي:

        using (Entities db = new Entities ())
        {
            var u1 = new User();
            db.Users.Add(u1);

            var u2 = new User();
            db.Users.Add(u2);

            u1.FriendCollection.Add(new Friend { User = u2 });
            u2.FriendCollection.Add(new Friend { User = u1 });

            try
            {
                var cnt = db.SaveChanges();
            }
            catch (DbEntityValidationException dbEx)
            {
                foreach (var validationErrors in dbEx.EntityValidationErrors)
                {
                    foreach (var validationError in validationErrors.ValidationErrors)
                    {
                        Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
                    }
                }
            }

يلقي SaveChanges خطأً كلما حاولت ملء فئة الصديق بكائن مستخدم يقول:

تم انتهاك قيد التعدد.الدور "Friend_User_Target" للعلاقة "Entities.Friend_User" له تعدد 1 أو 0..1.

إذا قمت بتعيين معرف المستخدم مثل هذا:

u1.FriendCollection.Add(new Friend { UserID = u2.ID });

هذا يسمح لي بحفظ الكيانات، ولكن ليس بشكل صحيح!

عندما أتصفح الكود يمكنني عزل المشكلة وإليك ما أجده:

b.FriendCollection.Add(new Friend { UserID = a.ID });
//Friend.UserID = 1
db.SaveChanges();
//Friend.UserID = 2 matching the b.ID

والآن يمكنني العودة إلى مثالي السابق وSaveChanges() دون إلقاء الخطأ إذا قمت بتعيين Friend.User إلى المستخدم المتصل.على سبيل المثال:

b.FriendCollection.Add(new Friend { User = b }); 
db.SaveChanges()

ولكن عندما أحاول تعيين مستخدم مختلف، تظهر لي رسالة الخطأ.على سبيل المثال:

b.FriendCollection.Add(new Friend { User = a }); 
db.SaveChanges()

انا حصلت:

تم انتهاك قيد التعدد.الدور "Friend_User_Target" للعلاقة "Entities.Friend_User" له تعدد 1 أو 0..1.

هل يمكن لأي أحد أن يخبرني كيف يمكنني إصلاح النموذج الخاص بي (باستخدام FluentAPI) حتى أتمكن من تعيين مستخدم مختلف إلى User.FriendCollection الخاص بي؟

هل كانت مفيدة؟

المحلول

التعيين غير صحيح، على الأقل غير صحيح بالنسبة لمعنى العلاقات في النموذج الخاص بك.

يقوم التعيين الخاص بك بإنشاء علاقة واحدة وخاصيتي التنقل User.FriendCollection و Friend.User هما طرفي هذه العلاقة الواحدة.لقد قمت بتعريفها كخصائص عكسية.

ولكن هذا يعني أنه إذا كان لديك مستخدم UserA لديه FriendB في ملف FriendCollection ال User في FriendB يجب أن يكون UserA وليس أي مستخدم آخر.يمكن لنموذجك فقط أن يعبر عن أن المستخدم صديق لنفسه، إذا جاز التعبير.لأنك تقوم بإضافة مستخدم آخر إلى المجموعة، فستحصل على استثناءات.

في رأيي الكيان Friend لا يمثل صديقًا = مستخدمًا آخر، ولكنه في الحقيقة يعبر عن علاقة.إنه نوع من الكيان الوسيط لعلاقة متعدد إلى متعدد بين المستخدمين وهذه العلاقة هي Friendship (أفضل أن أسميها بهذه الطريقة.)

على أية حال، يحتاج نموذجك إلى علاقتين.يمكنك ترك الكيانات كما هي ولكن استخدم هذا التعيين:

public class UserConfiguration : EntityTypeConfiguration<User>
{
    public UserConfiguration()
    {
        HasKey(x => x.ID);
        HasMany(x => x.FriendCollection)
            .WithRequired();
    }
}

public class FriendConfiguration : EntityTypeConfiguration<Friend>
{
    public FriendConfiguration()
    {
        HasKey(x => x.ID);
        HasRequired(x => x.User)
            .WithMany()
            .HasForeignKey(x => x.UserID)
            .WillCascadeOnDelete(false);
    }
}

(يعد تعطيل الحذف المتتالي في إحدى العلاقات ضروريًا لتجنب "استثناء مسار الحذف المتتالي المتعدد".)

لاحظ أن لديك الآن مفتاحين خارجيين في ملف Friend طاولة، UserID للثانية و User_ID للرسم الأول.يمكنك إعادة تسمية اسم العمود الافتراضي عن طريق الإضافة Map(m => m.MapKey("SomeUserID")) إلى الخريطة الأولى.

مع هذا التعيين، يجب أن يعمل رمز وحدة التحكم الخاصة بك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top