Skip to content

Commit

Permalink
Commands: Discover context types from migrations
Browse files Browse the repository at this point in the history
  • Loading branch information
bricelam committed Oct 13, 2014
1 parent 04a077b commit 4ce9a25
Show file tree
Hide file tree
Showing 17 changed files with 934 additions and 25 deletions.
7 changes: 7 additions & 0 deletions EntityFramework-2014.sln
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "EntityFramework.Redis.Funct
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "EntityFramework.Redis.Tests", "test\EntityFramework.Redis.Tests\EntityFramework.Redis.Tests.kproj", "{B0C91151-2400-43D3-B45A-3C88B2219790}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "EntityFramework.Commands.FunctionalTests", "test\EntityFramework.Commands.FunctionalTests\EntityFramework.Commands.FunctionalTests.kproj", "{CCEAA6B7-9270-4F5D-8F50-F2773F2A87CE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -213,6 +215,10 @@ Global
{B0C91151-2400-43D3-B45A-3C88B2219790}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B0C91151-2400-43D3-B45A-3C88B2219790}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B0C91151-2400-43D3-B45A-3C88B2219790}.Release|Any CPU.Build.0 = Release|Any CPU
{CCEAA6B7-9270-4F5D-8F50-F2773F2A87CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CCEAA6B7-9270-4F5D-8F50-F2773F2A87CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CCEAA6B7-9270-4F5D-8F50-F2773F2A87CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CCEAA6B7-9270-4F5D-8F50-F2773F2A87CE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -252,5 +258,6 @@ Global
{C6F4A609-6882-4C06-B0FB-EAE236456226} = {E7D68B03-3A5D-4710-9A1F-20D198E41F78}
{7C7057C9-EEB3-45E9-A660-235336474FBF} = {C605BAB7-B06E-4BDF-80B2-E661B7670E25}
{B0C91151-2400-43D3-B45A-3C88B2219790} = {C605BAB7-B06E-4BDF-80B2-E661B7670E25}
{CCEAA6B7-9270-4F5D-8F50-F2773F2A87CE} = {C605BAB7-B06E-4BDF-80B2-E661B7670E25}
EndGlobalSection
EndGlobal
7 changes: 7 additions & 0 deletions EntityFramework.sln
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EntityFramework.Performance
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Performance", "Performance", "{FBEBCED5-F50F-4F2F-954F-5F2E65777672}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EntityFramework.Commands.FunctionalTests", "test\EntityFramework.Commands.FunctionalTests\EntityFramework.Commands.FunctionalTests.csproj", "{43FC8426-D120-44F7-B6D7-6F256D78B5BE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -189,6 +191,10 @@ Global
{A01D56A2-5385-4049-A4B8-EC4D09228114}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A01D56A2-5385-4049-A4B8-EC4D09228114}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A01D56A2-5385-4049-A4B8-EC4D09228114}.Release|Any CPU.Build.0 = Release|Any CPU
{43FC8426-D120-44F7-B6D7-6F256D78B5BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{43FC8426-D120-44F7-B6D7-6F256D78B5BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{43FC8426-D120-44F7-B6D7-6F256D78B5BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{43FC8426-D120-44F7-B6D7-6F256D78B5BE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -224,5 +230,6 @@ Global
{9216D88D-CE9E-456F-9B77-1C43171633CB} = {FBEBCED5-F50F-4F2F-954F-5F2E65777672}
{A01D56A2-5385-4049-A4B8-EC4D09228114} = {FBEBCED5-F50F-4F2F-954F-5F2E65777672}
{FBEBCED5-F50F-4F2F-954F-5F2E65777672} = {547020C0-976F-4542-81CE-7FD465595614}
{43FC8426-D120-44F7-B6D7-6F256D78B5BE} = {547020C0-976F-4542-81CE-7FD465595614}
EndGlobalSection
EndGlobal
4 changes: 3 additions & 1 deletion src/EntityFramework.Commands/ContextTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,9 @@ private static IEnumerable<Type> FilterTypes(
var comparisonType = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;

return types.Where(
t => string.Equals(t.Name, name, comparisonType) || string.Equals(t.FullName, name, comparisonType));
t => string.Equals(t.Name, name, comparisonType)
|| string.Equals(t.FullName, name, comparisonType)
|| string.Equals(t.AssemblyQualifiedName, name, comparisonType));
}
}
}
16 changes: 10 additions & 6 deletions src/EntityFramework.Commands/Executor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ public GetContextType([NotNull] Executor executor, [NotNull] object handler, [No

public virtual string GetContextTypeImpl([CanBeNull] string name)
{
// TODO: Assembly-qualified
return _migrationTool.GetContextType(name).FullName;
return _migrationTool.GetContextType(name).AssemblyQualifiedName;
}

public class AddMigration : OperationBase
Expand Down Expand Up @@ -148,16 +147,21 @@ public GetContextTypes([NotNull] Executor executor, [NotNull] object handler, [N
public virtual IEnumerable<IDictionary> GetContextTypesImpl()
{
var contextTypes = _migrationTool.GetContextTypes().ToArray();
var groups = contextTypes.GroupBy(t => t.Name).ToArray();
var nameGroups = contextTypes.GroupBy(t => t.Name).ToArray();
var fullNameGroups = contextTypes.GroupBy(t => t.FullName).ToArray();

// TODO: Assembly-qualified
return contextTypes.Select(
t =>
{
var result = new Hashtable();
result["AssemblyQualifiedName"] = t.AssemblyQualifiedName;
result["FullName"] = t.FullName;
result["Name"] = t.Name;
result["SafeName"] = groups.Count(g => g.Key == t.Name) == 1 ? t.Name : t.FullName;
result["SafeName"] = nameGroups.Count(g => g.Key == t.Name) == 1
? t.Name
: fullNameGroups.Count(g => g.Key == t.FullName) == 1
? t.FullName
: t.AssemblyQualifiedName;
return result;
});
Expand Down Expand Up @@ -223,7 +227,7 @@ public virtual void Execute([NotNull] Action action)
}
catch (Exception ex)
{
_handler.OnError(ex.GetType().FullName, ex.Message, ex.ToString());
_handler.OnError(ex.GetType().AssemblyQualifiedName, ex.Message, ex.ToString());
}
}

Expand Down
20 changes: 12 additions & 8 deletions src/EntityFramework.Commands/MigrationTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,16 +98,11 @@ public virtual IEnumerable<string> WriteMigration(
yield return modelSnapshotFile;
}

// TODO: Find in _assembly instead filtering by contextTypeName (See #628)
public virtual IEnumerable<IMigrationMetadata> GetMigrations([CanBeNull] string contextTypeName)
{
var contextType = GetContextType(contextTypeName);
using (var context = CreateContext(contextType))
{
var migrator = CreateMigrator(context);

return migrator.GetLocalMigrations();
}
return MigrationAssembly.LoadMigartions(GetMigrationTypes(), contextType);
}

public virtual string ScriptMigration(
Expand Down Expand Up @@ -155,10 +150,14 @@ public virtual Type GetContextType([CanBeNull] string name)
return ContextTool.SelectType(GetContextTypes(), name);
}

// TODO: Find from migration types instead (See #628)
public virtual IEnumerable<Type> GetContextTypes()
{
return ContextTool.GetContextTypes(_assembly);
return ContextTool.GetContextTypes(_assembly)
.Concat(
GetMigrationTypes()
.Select(MigrationAssembly.TryGetContextType)
.Where(t => t != null))
.Distinct();
}

private DbContext CreateContext(Type type)
Expand All @@ -177,5 +176,10 @@ private Migrator CreateMigrator(DbContext context)
{
return context.Configuration.Services.ServiceProvider.GetService<Migrator>();
}

private IEnumerable<Type> GetMigrationTypes()
{
return MigrationAssembly.GetMigrationTypes(_assembly);
}
}
}
36 changes: 27 additions & 9 deletions src/EntityFramework.Migrations/Infrastructure/MigrationAssembly.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,33 @@ public virtual IModel Model
get { return _model ?? (_model = LoadModel()); }
}

public static IEnumerable<Type> GetMigrationTypes([NotNull] Assembly assembly)
{
Check.NotNull(assembly, "assembly");

return assembly.GetAccessibleTypes()
.Where(t => t.GetTypeInfo().IsSubclassOf(typeof(Migration))
&& t.GetPublicConstructor() != null
&& !t.GetTypeInfo().IsAbstract
&& !t.GetTypeInfo().IsGenericType);
}

public static IEnumerable<IMigrationMetadata> LoadMigartions(
[NotNull] IEnumerable<Type> migrationTypes,
[CanBeNull] Type contextType)
{
Check.NotNull(migrationTypes, "migrationTypes");

return migrationTypes
.Where(t => TryGetContextType(t) == contextType)
.Select(t => (IMigrationMetadata)Activator.CreateInstance(t))
.OrderBy(m => m.MigrationId);
}

protected virtual IReadOnlyList<IMigrationMetadata> LoadMigrations()
{
var contextType = ContextConfiguration.Context.GetType();
return Assembly.GetAccessibleTypes()
.Where(t => t.GetTypeInfo().IsSubclassOf(typeof(Migration))
&& t.GetPublicConstructor() != null
&& !t.GetTypeInfo().IsAbstract
&& !t.GetTypeInfo().IsGenericType
&& TryGetContextType(t) == contextType)
.Select(t => (IMigrationMetadata)Activator.CreateInstance(t))
.OrderBy(m => m.MigrationId)
return LoadMigartions(GetMigrationTypes(Assembly), contextType)
.ToArray();
}

Expand All @@ -75,8 +91,10 @@ protected virtual IModel LoadModel()
: null;
}

protected virtual Type TryGetContextType(Type type)
public static Type TryGetContextType([NotNull] Type type)
{
Check.NotNull(type, "type");

var contextTypeAttribute = type.GetTypeInfo().GetCustomAttribute<ContextTypeAttribute>(inherit: true);

return contextTypeAttribute != null ? contextTypeAttribute.ContextType : null;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Import Project="..\..\tools\EntityFramework.props" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{43FC8426-D120-44F7-B6D7-6F256D78B5BE}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Microsoft.Data.Entity.Commands</RootNamespace>
<AssemblyName>EntityFramework.Commands.FunctionalTests</AssemblyName>
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;NET451</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;NET451</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<PackageReference Include="System.Data.Common">
<TargetFramework>net451</TargetFramework>
</PackageReference>
<PackageReference Include="Microsoft.Bcl.Immutable">
<TargetFramework>portable-net45+win8+wpa81</TargetFramework>
<Assemblies>System.Collections.Immutable</Assemblies>
</PackageReference>
<PackageReference Include="Microsoft.Bcl.Metadata">
<TargetFramework>portable-net45+win8</TargetFramework>
<Assemblies>System.Reflection.Metadata</Assemblies>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.Common">
<Assemblies>Microsoft.CodeAnalysis;Microsoft.CodeAnalysis.Desktop</Assemblies>
<TargetFramework>net45</TargetFramework>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp">
<TargetFramework>net45</TargetFramework>
<Assemblies>Microsoft.CodeAnalysis.CSharp;Microsoft.CodeAnalysis.CSharp.Desktop</Assemblies>
</PackageReference>
<PackageReference Include="xunit.abstractions">
<TargetFramework>net45</TargetFramework>
</PackageReference>
<PackageReference Include="xunit.assert">
<TargetFramework>net45</TargetFramework>
</PackageReference>
<PackageReference Include="xunit.core">
<TargetFramework>net45</TargetFramework>
<Assemblies>xunit.core;xunit.runner.tdnet</Assemblies>
</PackageReference>
<PackageReference Include="xunit.execution">
<TargetFramework>net45</TargetFramework>
</PackageReference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\src\EntityFramework.Commands\tools\Handler.cs">
<Link>Handler.cs</Link>
</Compile>
<Compile Include="ExecutorTest.cs" />
<Compile Include="TestUtilities\BuildReference.cs" />
<Compile Include="TestUtilities\BuildFileResult.cs" />
<Compile Include="TestUtilities\BuildSource.cs" />
<Compile Include="TestUtilities\CommandException.cs" />
<Compile Include="TestUtilities\ExecutorWrapper.cs" />
<Compile Include="TestUtilities\TempDirectory.cs" />
<None Include="project.json" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\EntityFramework.Commands\EntityFramework.Commands.csproj">
<Project>{10ca97eb-e724-4f08-86af-f301f2b0bfff}</Project>
<Name>EntityFramework.Commands</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\EntityFramework.Migrations\EntityFramework.Migrations.csproj">
<Project>{6e38b72f-31da-4aef-8f34-b8269572ec6b}</Project>
<Name>EntityFramework.Migrations</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\EntityFramework.SQLite\EntityFramework.SQLite.csproj">
<Project>{4cc98896-fe91-4f16-ae60-d6ff9e905836}</Project>
<Name>EntityFramework.SQLite</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="__ToolsVersion__" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>cceaa6b7-9270-4f5d-8f50-f2773f2a87ce</ProjectGuid>
<OutputType>Library</OutputType>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'" Label="Configuration">
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'" Label="Configuration">
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>
Loading

0 comments on commit 4ce9a25

Please sign in to comment.