-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add SeedData #9772
Add SeedData #9772
Conversation
Rebase needed. |
I'll rebase when the PR is approved. Incremental rebases are time-consuming as I cannot rebase the original commit. |
/// This API supports the Entity Framework Core infrastructure and is not intended to be used | ||
/// directly from your code. This API may change or be removed in future releases. | ||
/// </summary> | ||
public virtual IReadOnlyList<InternalEntityEntry> GetEntriesToSave() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public virtual IReadOnlyList GetEntriesToSave() [](start = 8, length = 68)
Should this really be exposed publicly? What ends up using the InternalEntityEntries? Is it provider code at all?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IStateManager
is an Internal service
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was just concerned that it might be consumed by code that could be overridden by a provider--the same reason we introduced IUpdateEntry for the update pipeline. Looks like this isn't the case, so no problem. However, did we consider returning IUpdateEntrys instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll change it to return IReadOnlyList<IUpdateEntry>
|
||
entry.ToEntityEntry().CurrentValues.SetValues(values); | ||
return entry; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method seems like it needs some work. There is duplicated logic here with other GetOrCreate methods, and this could make better use of the materializer.
// Remove when issue #749 is fixed | ||
var principal = foreignKey.DependentToPrincipal?.IsShadowProperty ?? true | ||
? null | ||
: foreignKey.DependentToPrincipal.GetGetter().GetClrValue(entry.Entity); | ||
InternalEntityEntry principalEntry = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the consequence of just skipping propagation here?
return propertyBase is INavigation && propertyBase.IsShadowProperty // Remove when issue #749 is fixed | ||
? null | ||
: _storeGeneratedValues.TryGetValue(propertyBase, out var value) | ||
? value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm concerned in general about the hacks for shadow nav props--for example, how they may influence other code paths rather than just seeding. Do we have a plan to either fix #749 in 2.1, or make the hacks less hacky?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that these hacks have any functional impact on non-seeding scenarios. If we have time to do #749 in 2.1 I would prefer it instead of trying to improve the hacks further.
"TypeId": "public class Microsoft.EntityFrameworkCore.Migrations.Operations.UpdateDataOperation : Microsoft.EntityFrameworkCore.Migrations.Operations.MigrationOperation", | ||
"Kind": "Removal" | ||
}, | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are here because we added a base class? So, not really breaks?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, seems to be a bug in the API tool
@@ -127,15 +163,26 @@ public virtual string OriginalParameterName | |||
/// <summary> | |||
/// The original value of the property mapped to this column. | |||
/// </summary> | |||
public virtual object OriginalValue => Entry.GetOriginalValue(Property); | |||
public virtual object OriginalValue => Entry == null ? _originalValue : Entry.GetOriginalValue(Property); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Entry == null [](start = 47, length = 13)
What is it that allows Entry to be null now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new constructor.
This is needed because when generating SQL when applying a migration we might not have an IModel
anymore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but make sure we follow up on the state manager changes stuff and the shadow nav stuff before we ship. Maybe create issues if needed?
b0fb0e4
to
6187ade
Compare
I've added a todo list to #629 to track the outsanding issues roughly in decreasing priority order. Let me know if I missed anything. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the late review.
Table = c.TableName, | ||
KeyColumns = c.ColumnModifications.Select(col => col.ColumnName).ToArray(), | ||
KeyValues = ToMultidimensionalArray(c.ColumnModifications.Select(col => col.Value).ToArray()) | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should look into accumulating these. Instead of creating one per row, if the last operation was the same type for the same table, we should just append the values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it's on the ToDo list: #629
if (source.EntityTypes.Count != 1 || target.EntityTypes.Count != 1) | ||
{ | ||
// Table splitting not supported | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should it throw or is is made impossible at a higher level?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's on the ToDo list: #629
=> Diff(source, target, new DiffContext(source, target)).Any(); | ||
{ | ||
var result = Diff(source, target, new DiffContext(source, target)).Any(); | ||
StateManager.ResetState(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you hit issues if you call HasDifferences
during SaveChanges
? This seems like a dangerous side affect...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean concurrently? We definitely don't support that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I imagined something like this:
db.Add(customer);
if (differ.HasDiferences(modelSnapshot, db.Model)
Log.Warn("Someone forgot to migrate. This might fail.");
db.SaveChanges();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still doesn't look like an important enough scenario, but I am open to hearing opinions from others
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Coming very late to this comment, but I need more context. It seems it would be good to discuss it when @bricelam is present. @AndriySvyryd can you please file something so that we remember?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I already fixed this in the new PR that's currently open
/// The commands that correspond to this operation. | ||
/// </summary> | ||
public virtual IEnumerable<ModificationCommand> ModificationCommands | ||
=> _modificationCommands ?? (_modificationCommands = GenerateModificationCommands()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't feel like a property to me. Lets discuss during API review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to discuss, I'll just make it a method
|
||
builder | ||
.AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the last statement is in a separate batch now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Appears so. I'll revert this when I add batching back
x.ToTable("Firefly", "dbo"); | ||
x.Property<int>("Id"); | ||
x.HasKey("Id"); | ||
}), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like a bad merge.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks more like a bad PR differ
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, the old code didn't have HasKey()
and used chaining (not a closure) on the target model.
{ | ||
x.ToTable("Firefly", "dbo"); | ||
x.Property<int>("Id"); | ||
x.HasKey("Id"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary HasKey()
calls were removed from these tests.
Fixes #629
Further improvements will be done in separate PRs