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
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":
Guild classGuild 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
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.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.