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 IsTemporary API on PropertyEntry #6314

Merged
merged 1 commit into from
Aug 16, 2016
Merged
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
Original file line number Diff line number Diff line change
@@ -4024,7 +4024,13 @@ protected class Game

public virtual ICollection<Level> Levels { get; set; } = new List<Level>();
}


protected class TestTemp
{
public int Id { get; set; }
public int NotId { get; set; }
}

protected void AssertFixup(DbContext context, Action asserts)
{
asserts();
@@ -4072,6 +4078,8 @@ public abstract class StoreGeneratedFixupFixtureBase

protected virtual void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<TestTemp>();

modelBuilder.Entity<Parent>(b =>
{
b.HasKey(e => new { e.Id1, e.Id2 });
Original file line number Diff line number Diff line change
@@ -3,7 +3,6 @@

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Internal;
using Xunit;

@@ -40,7 +39,7 @@ public virtual void Identity_property_on_Added_entity_with_temporary_value_gets_
using (var context = CreateContext())
{
var entry = context.Add(new Gumball { Identity = "Masami" });
entry.GetInfrastructure().MarkAsTemporary(entry.Property(e => e.Identity).Metadata);
entry.Property(e => e.Identity).IsTemporary = true;

context.SaveChanges();
id = entry.Entity.Id;
@@ -214,7 +213,7 @@ public virtual void Always_identity_property_on_Added_entity_with_temporary_valu
using (var context = CreateContext())
{
var entry = context.Add(new Gumball { AlwaysIdentity = "Masami" });
entry.GetInfrastructure().MarkAsTemporary(entry.Property(e => e.AlwaysIdentity).Metadata);
entry.Property(e => e.AlwaysIdentity).IsTemporary = true;

context.SaveChanges();
id = entry.Entity.Id;
@@ -388,7 +387,7 @@ public virtual void Computed_property_on_Added_entity_with_temporary_value_gets_
using (var context = CreateContext())
{
var entry = context.Add(new Gumball { Computed = "Masami" });
entry.GetInfrastructure().MarkAsTemporary(entry.Property(e => e.Computed).Metadata);
entry.Property(e => e.Computed).IsTemporary = true;

context.SaveChanges();
id = entry.Entity.Id;
@@ -562,7 +561,7 @@ public virtual void Always_computed_property_on_Added_entity_with_temporary_valu
using (var context = CreateContext())
{
var entry = context.Add(new Gumball { AlwaysComputed = "Masami" });
entry.GetInfrastructure().MarkAsTemporary(entry.Property(e => e.AlwaysComputed).Metadata);
entry.Property(e => e.AlwaysComputed).IsTemporary = true;

context.SaveChanges();
id = entry.Entity.Id;
15 changes: 13 additions & 2 deletions src/Microsoft.EntityFrameworkCore/ChangeTracking/PropertyEntry.cs
Original file line number Diff line number Diff line change
@@ -47,8 +47,8 @@ private static IProperty GetProperty(InternalEntityEntry internalEntry, string n
if (internalEntry.EntityType.FindNavigation(name) != null)
{
throw new InvalidOperationException(
CoreStrings.PropertyIsNavigation(name, internalEntry.EntityType.DisplayName(),
nameof(EntityEntry.Property), nameof(EntityEntry.Reference), nameof(EntityEntry.Collection)));
CoreStrings.PropertyIsNavigation(name, internalEntry.EntityType.DisplayName(),
nameof(EntityEntry.Property), nameof(EntityEntry.Reference), nameof(EntityEntry.Collection)));
}
throw new InvalidOperationException(CoreStrings.PropertyNotFound(name, internalEntry.EntityType.DisplayName()));
}
@@ -66,6 +66,17 @@ public override bool IsModified
set { InternalEntry.SetPropertyModified(Metadata, changeState: true, isModified: value); }
}

/// <summary>
/// Gets or sets a value indicating whether the value of this property is considered a
/// temporary value which will be replaced by a value generated from the store when
/// <see cref="DbContext.SaveChanges()" />is called.
/// </summary>
public virtual bool IsTemporary
{
get { return InternalEntry.HasTemporaryValue(Metadata); }
set { InternalEntry.MarkAsTemporary(Metadata, value); }
}

/// <summary>
/// Gets the metadata that describes the facets of this property and how it maps to the database.
/// </summary>
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
using Microsoft.EntityFrameworkCore.Specification.Tests;
using Microsoft.EntityFrameworkCore.Storage.Internal;
using Microsoft.Extensions.DependencyInjection;
using Xunit;

namespace Microsoft.EntityFrameworkCore.InMemory.FunctionalTests
{
@@ -16,6 +17,25 @@ public StoreGeneratedFixupInMemoryTest(StoreGeneratedFixupInMemoryFixture fixtur
{
}

[Fact]
public void InMemory_database_does_not_use_temp_values()
{
using (var context = CreateContext())
{
var entry = context.Add(new TestTemp());

Assert.False(entry.Property(e => e.Id).IsTemporary);
Assert.False(entry.Property(e => e.NotId).IsTemporary);

var tempValue = entry.Property(e => e.Id).CurrentValue;

context.SaveChanges();

Assert.False(entry.Property(e => e.Id).IsTemporary);
Assert.Equal(tempValue, entry.Property(e => e.Id).CurrentValue);
}
}

protected override void MarkIdsTemporary(StoreGeneratedFixupContext context, object dependent, object principal)
{
}
Original file line number Diff line number Diff line change
@@ -2,10 +2,10 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Specification.Tests;
using Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests.Utilities;
using Microsoft.Extensions.DependencyInjection;
using Xunit;

namespace Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests
{
@@ -17,24 +17,43 @@ public StoreGeneratedFixupSqlServerTest(StoreGeneratedFixupSqlServerFixture fixt
{
}

[Fact]
public void Temp_values_are_replaced_on_save()
{
using (var context = CreateContext())
{
var entry = context.Add(new TestTemp());

Assert.True(entry.Property(e => e.Id).IsTemporary);
Assert.False(entry.Property(e => e.NotId).IsTemporary);

var tempValue = entry.Property(e => e.Id).CurrentValue;

context.SaveChanges();

Assert.False(entry.Property(e => e.Id).IsTemporary);
Assert.NotEqual(tempValue, entry.Property(e => e.Id).CurrentValue);
}
}

protected override void MarkIdsTemporary(StoreGeneratedFixupContext context, object dependent, object principal)
{
var entry = context.Entry(dependent);
entry.GetInfrastructure().MarkAsTemporary(entry.Property("Id1").Metadata);
entry.GetInfrastructure().MarkAsTemporary(entry.Property("Id2").Metadata);
entry.Property("Id1").IsTemporary = true;
entry.Property("Id2").IsTemporary = true;

entry = context.Entry(principal);
entry.GetInfrastructure().MarkAsTemporary(entry.Property("Id1").Metadata);
entry.GetInfrastructure().MarkAsTemporary(entry.Property("Id2").Metadata);
entry.Property("Id1").IsTemporary = true;
entry.Property("Id2").IsTemporary = true;
}

protected override void MarkIdsTemporary(StoreGeneratedFixupContext context, object game, object level, object item)
{
var entry = context.Entry(game);
entry.GetInfrastructure().MarkAsTemporary(entry.Property("Id").Metadata);
entry.Property("Id").IsTemporary = true;

entry = context.Entry(item);
entry.GetInfrastructure().MarkAsTemporary(entry.Property("Id").Metadata);
entry.Property("Id").IsTemporary = true;
}

protected override bool EnforcesFKs => true;
Original file line number Diff line number Diff line change
@@ -2,9 +2,9 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Specification.Tests;
using Microsoft.Extensions.DependencyInjection;
using Xunit;

namespace Microsoft.EntityFrameworkCore.Sqlite.FunctionalTests
{
@@ -16,24 +16,45 @@ public StoreGeneratedFixupSqliteTest(StoreGeneratedFixupSqliteFixture fixture)
{
}

[Fact]
public void Temp_values_can_be_made_permanent()
{
using (var context = CreateContext())
{
var entry = context.Add(new TestTemp());

Assert.True(entry.Property(e => e.Id).IsTemporary);
Assert.False(entry.Property(e => e.NotId).IsTemporary);

var tempValue = entry.Property(e => e.Id).CurrentValue;

entry.Property(e => e.Id).IsTemporary = false;

context.SaveChanges();

Assert.False(entry.Property(e => e.Id).IsTemporary);
Assert.Equal(tempValue, entry.Property(e => e.Id).CurrentValue);
}
}

protected override void MarkIdsTemporary(StoreGeneratedFixupContext context, object dependent, object principal)
{
// TODO: Uncomment this when #6292 is fixed
//var entry = context.Entry(dependent);
//entry.GetInfrastructure().MarkAsTemporary(entry.Property("Id1").Metadata);
//entry.Property("Id1").IsTemporary = true;

//entry = context.Entry(principal);
//entry.GetInfrastructure().MarkAsTemporary(entry.Property("Id1").Metadata);
//entry.Property("Id1").IsTemporary = true;
}

protected override void MarkIdsTemporary(StoreGeneratedFixupContext context, object game, object level, object item)
{
// TODO: Uncomment this when #6292 is fixed
//var entry = context.Entry(game);
//entry.GetInfrastructure().MarkAsTemporary(entry.Property("Id").Metadata);
//entry.Property("Id").IsTemporary = true;

//entry = context.Entry(item);
//entry.GetInfrastructure().MarkAsTemporary(entry.Property("Id").Metadata);
//entry.Property("Id").IsTemporary = true;
}

protected override bool EnforcesFKs => true;