Skip to content
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

Merged
merged 2 commits into from
Sep 13, 2017
Merged

Add SeedData #9772

merged 2 commits into from
Sep 13, 2017

Conversation

AndriySvyryd
Copy link
Member

Fixes #629

Further improvements will be done in separate PRs

@smitpatel
Copy link
Contributor

Rebase needed.

@AndriySvyryd
Copy link
Member Author

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()
Copy link
Contributor

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?

Copy link
Member Author

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

Copy link
Contributor

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?

Copy link
Member Author

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;
}
Copy link
Contributor

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;
Copy link
Contributor

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
Copy link
Contributor

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?

Copy link
Member Author

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"
},
{
Copy link
Contributor

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?

Copy link
Member Author

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);
Copy link
Contributor

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?

Copy link
Member Author

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

Copy link
Contributor

@ajcvickers ajcvickers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit: 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?

@AndriySvyryd
Copy link
Member Author

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.

Copy link
Contributor

@bricelam bricelam left a 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())
};
Copy link
Contributor

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.

Copy link
Member Author

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;
Copy link
Contributor

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?

Copy link
Member Author

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();
Copy link
Contributor

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...

Copy link
Member Author

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.

Copy link
Contributor

@bricelam bricelam Sep 13, 2017

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();

Copy link
Member Author

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

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

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?

Copy link
Member Author

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());
Copy link
Contributor

@bricelam bricelam Sep 13, 2017

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.

Copy link
Member Author

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)
Copy link
Contributor

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?

Copy link
Member Author

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");
}),
Copy link
Contributor

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.

Copy link
Member Author

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

Copy link
Contributor

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");
Copy link
Contributor

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants