Entity Framework relationships between different DbContext and different schemas

后端 未结 4 1327
忘掉有多难
忘掉有多难 2020-12-17 14:56

So, I have two main objects, Member and Guild. One Member can own a Guild and one Guild can have multiple Members.

I have the Members class in a separate DbContext

4条回答
  •  Happy的楠姐
    2020-12-17 15:16

    This is working code:

    In assembly "M":

    public class Member
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
    
    public class MemberMapping : EntityTypeConfiguration
    {
        public MemberMapping()
        {
            this.HasKey(m => m.Id);
            this.Property(m => m.Name).IsRequired();
        }
    }
    

    In assemby "G":

    • your Guild class
    • your Guild mapping, albeit with WillCascadeOnDelete(false) in the LeaderMemberInfo mapping.
    • modelBuilder.Configurations.Add(new GuildMapping()); and modelBuilder.Configurations.Add(new MemberMapping());

    Code:

    var m = new Member { Name = "m1" };
    var lm = new Member { Name = "leader" };
    var g = new Guild { Name = "g1" };
    g.LeaderMemberInfo = lm;
    g.Members.Add(lm);
    g.Members.Add(m);
    c.Set().Add(g);
    c.SaveChanges();
    

    Executed SQL:

    INSERT [dbo].[Members]([Name])
    VALUES (@0)
    SELECT [Id]
    FROM [dbo].[Members]
    WHERE @@ROWCOUNT > 0 AND [Id] = scope_identity()
    -- @0: 'leader' (Type = String, Size = -1)
    
    INSERT [dbo].[Guilds]([MemberID], [Name])
    VALUES (@0, @1)
    SELECT [ID]
    FROM [dbo].[Guilds]
    WHERE @@ROWCOUNT > 0 AND [ID] = scope_identity()
    -- @0: '1' (Type = Int32)
    -- @1: 'g1' (Type = String, Size = -1)
    
    INSERT [dbo].[GuildsMembers]([GuildID], [MemberID])
    VALUES (@0, @1)
    -- @0: '1' (Type = Int32)
    -- @1: '1' (Type = Int32)
    
    INSERT [dbo].[Members]([Name])
    VALUES (@0)
    SELECT [Id]
    FROM [dbo].[Members]
    WHERE @@ROWCOUNT > 0 AND [Id] = scope_identity()
    -- @0: 'm1' (Type = String, Size = -1)
    
    INSERT [dbo].[GuildsMembers]([GuildID], [MemberID])
    VALUES (@0, @1)
    -- @0: '1' (Type = Int32)
    -- @1: '2' (Type = Int32)
    

    This also works when associating existing objects.


    Original answer for more general case:

    You can't combine types in different contexts into one object graph. That means, you can't do something like

    from a in context.As
    join b in context.Bs on ...
    

    ...because there's always one context that should create the whole SQL query, so it should have all required mapping information.

    You can register the same type into two different contexts though, even from different assemblies. So you could map Member in the context in Guild's assembly, let's call it contextG, but only if

    1. Member doesn't refer to other types that aren't mapped in contextG. This may imply that navigation properties in Member must be ignored explicitly.
    2. Member can't refer to types in contextG, because these types are not part of Member's context.

    If any of these conditions can't be fulfilled the best you can do is create a new Member class in Guild's assembly and register its mapping in the context. Maybe you want to use a different name to prevent ambiguity, but this is about the only alternative left.

提交回复
热议问题