Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/EFCore/Metadata/Internal/ForeignKeyExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,8 @@ public static void GetPropertiesWithMinimalOverlapIfPossible(
for (var i = 0; i < count; i++)
{
var dependentProperty = foreignKey.Properties[i];

if (dependentProperty.GetContainingForeignKeys().Count() > 1)
if (dependentProperty.GetContainingForeignKeys().Count() > 1
|| dependentProperty.IsKey())
{
if (ReferenceEquals(foreignKeyProperties, foreignKey.Properties))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,30 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con
b.Property(e => e.PrimaryGroup).ValueGeneratedOnAdd();
});

modelBuilder.Entity<Group37310>(b =>
{
b.Property(e => e.Id).ValueGeneratedNever();
b.HasOne(e => e.GroupOwner)
.WithMany()
.HasForeignKey(e => new { e.Id, e.GroupOwnerId });
});

modelBuilder.Entity<GroupMember37310>(b =>
{
b.HasKey(e => new { e.GroupId, e.UserId });
b.HasOne(e => e.User)
.WithMany(e => e.Groups)
.HasForeignKey(e => e.UserId);
b.HasOne(e => e.Group)
.WithMany(e => e.Members)
.HasForeignKey(e => e.GroupId);
});

modelBuilder.Entity<User37310>(b =>
{
b.Property(e => e.Id).ValueGeneratedNever();
});

modelBuilder.Entity<ParentWithClientSetDefault>(b =>
{
b.Property(e => e.Id).ValueGeneratedNever();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2315,4 +2315,122 @@ public virtual Task Mark_explicitly_set_stable_dependent_appropriately_when_deep
_ = async ? await context.SaveChangesAsync() : context.SaveChanges();
});
}

#region Issue37310
[ConditionalTheory, InlineData(false), InlineData(true)]
public virtual async Task Can_update_many_to_many_and_reference_with_composite_key(bool async)
=> await ExecuteWithStrategyInTransactionAsync(
async context =>
{
var group = new Group37310 { Id = 1 };
var user = new User37310 { Id = 1 };
var member = new GroupMember37310 { UserId = 1, GroupId = 1 };

context.Set<Group37310>().Add(group);
context.Set<User37310>().Add(user);
context.Set<GroupMember37310>().Add(member);

_ = async
? await context.SaveChangesAsync()
: context.SaveChanges();
},
async context =>
{
var group = async
? await context.Set<Group37310>().Include(x => x.Members).SingleAsync()
: context.Set<Group37310>().Include(x => x.Members).Single();

group.Members = new ObservableHashSet<GroupMember37310>(ReferenceEqualityComparer.Instance)
{
new GroupMember37310 { UserId = 1, GroupId = 1 }
};
group.GroupOwnerId = 1;

_ = async
? await context.SaveChangesAsync()
: context.SaveChanges();
});

protected class User37310 : NotifyingEntity
{
private int _id;
private ICollection<GroupMember37310> _groups = new ObservableHashSet<GroupMember37310>(ReferenceEqualityComparer.Instance);

public int Id
{
get => _id;
set => SetWithNotify(value, ref _id);
}

public ICollection<GroupMember37310> Groups
{
get => _groups;
set => SetWithNotify(value, ref _groups);
}
}

protected class Group37310 : NotifyingEntity
{
private int _id;
private int? _groupOwnerId;
private GroupMember37310 _groupOwner;
private ICollection<GroupMember37310> _members = new ObservableHashSet<GroupMember37310>(ReferenceEqualityComparer.Instance);

public int Id
{
get => _id;
set => SetWithNotify(value, ref _id);
}

public int? GroupOwnerId
{
get => _groupOwnerId;
set => SetWithNotify(value, ref _groupOwnerId);
}

public GroupMember37310 GroupOwner
{
get => _groupOwner;
set => SetWithNotify(value, ref _groupOwner);
}

public ICollection<GroupMember37310> Members
{
get => _members;
set => SetWithNotify(value, ref _members);
}
}

protected class GroupMember37310 : NotifyingEntity
{
private int _groupId;
private Group37310 _group;
private int _userId;
private User37310 _user;

public int GroupId
{
get => _groupId;
set => SetWithNotify(value, ref _groupId);
}

public Group37310 Group
{
get => _group;
set => SetWithNotify(value, ref _group);
}

public int UserId
{
get => _userId;
set => SetWithNotify(value, ref _userId);
}

public User37310 User
{
get => _user;
set => SetWithNotify(value, ref _user);
}
}
#endregion
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ public override Task Throws_for_single_property_bool_key_with_default_value_gene
public override Task Throws_for_single_property_nullable_bool_key_with_default_value_generation(bool async, bool? initialValue)
=> Task.CompletedTask;

// No owned types
public override Task Can_update_many_to_many_and_reference_with_composite_key(bool async)
=> Task.CompletedTask;

protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction)
=> facade.UseTransaction(transaction.GetDbTransaction());

Expand Down