提交 dcb367e7 编写于 作者: S Shay Rojansky

Initial import from Npgsql repository

From commit bb43e2282fb13b0deb931d199c95d07ab84169a0.
Project does not compile.
上级
; Top-most EditorConfig file
root = true
; Unix-style newlines
[*]
end_of_line = LF
; 4-column space indentation
[*.cs]
indent_style = space
indent_size = 4
; trim_trailing_whitespace = true
insert_final_newline = true
* text=auto
*.cs text=auto diff=csharp
*.csproj text=auto
*.sln text=auto
*.resx text=auto
*.xml text=auto
*.txt text=auto
packages/ binary
.DS_Store
*.resources
*.suo
*.user
*.sln.docstates
*.userprefs
/*.nupkg
.nuget/
[Bb]in/
[Bb]uild/
[Oo]bj/
[Oo]bj/
packages/*/
packages.stable
artifacts/
# Roslyn cache directories
*.ide/
*.lock.json
assembly-versioning-scheme: MajorMinorPatch
mode: ContinuousDeployment

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25123.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{8A657AC5-150F-4F55-8D9E-4F1A56D62D60}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E3B16670-40A6-4B2A-91F3-A1B214479954}"
ProjectSection(SolutionItems) = preProject
global.json = global.json
NuGet.Config = NuGet.Config
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{802E669C-6885-4E60-9CFB-8CFB47EAF16A}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Npgsql.EntityFrameworkCore.PostgreSQL", "src\Npgsql.EntityFrameworkCore.PostgreSQL\Npgsql.EntityFrameworkCore.PostgreSQL.xproj", "{0F7E25EB-E266-477A-88F1-E210D013720F}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Npgsql.EntityFrameworkCore.PostgreSQL.Design", "src\Npgsql.EntityFrameworkCore.PostgreSQL.Design\Npgsql.EntityFrameworkCore.PostgreSQL.Design.xproj", "{C115C84A-AFCE-4796-A155-9CEE4C141938}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Npgsql.EntityFrameworkCore.PostgreSQL.Design.FunctionalTests", "test\Npgsql.EntityFrameworkCore.PostgreSQL.Design.FunctionalTests\Npgsql.EntityFrameworkCore.PostgreSQL.Design.FunctionalTests.xproj", "{5336F099-DFF4-4439-9022-169AEB1FA737}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Npgsql.EntityFrameworkCore.PostgreSQL.Tests", "test\Npgsql.EntityFrameworkCore.PostgreSQL.Tests\Npgsql.EntityFrameworkCore.PostgreSQL.Tests.xproj", "{0F64B74C-8869-4352-9AF5-A4BF0927BCF1}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Npgsql.EntityFrameworkCore.PostgreSQL.FunctionalTests", "test\Npgsql.EntityFrameworkCore.PostgreSQL.FunctionalTests\Npgsql.EntityFrameworkCore.PostgreSQL.FunctionalTests.xproj", "{F33996A5-AAB6-4EC0-A865-E80AD16F3163}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0F7E25EB-E266-477A-88F1-E210D013720F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0F7E25EB-E266-477A-88F1-E210D013720F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0F7E25EB-E266-477A-88F1-E210D013720F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0F7E25EB-E266-477A-88F1-E210D013720F}.Release|Any CPU.Build.0 = Release|Any CPU
{C115C84A-AFCE-4796-A155-9CEE4C141938}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C115C84A-AFCE-4796-A155-9CEE4C141938}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C115C84A-AFCE-4796-A155-9CEE4C141938}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C115C84A-AFCE-4796-A155-9CEE4C141938}.Release|Any CPU.Build.0 = Release|Any CPU
{5336F099-DFF4-4439-9022-169AEB1FA737}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5336F099-DFF4-4439-9022-169AEB1FA737}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5336F099-DFF4-4439-9022-169AEB1FA737}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5336F099-DFF4-4439-9022-169AEB1FA737}.Release|Any CPU.Build.0 = Release|Any CPU
{0F64B74C-8869-4352-9AF5-A4BF0927BCF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0F64B74C-8869-4352-9AF5-A4BF0927BCF1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0F64B74C-8869-4352-9AF5-A4BF0927BCF1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0F64B74C-8869-4352-9AF5-A4BF0927BCF1}.Release|Any CPU.Build.0 = Release|Any CPU
{F33996A5-AAB6-4EC0-A865-E80AD16F3163}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F33996A5-AAB6-4EC0-A865-E80AD16F3163}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F33996A5-AAB6-4EC0-A865-E80AD16F3163}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F33996A5-AAB6-4EC0-A865-E80AD16F3163}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{0F7E25EB-E266-477A-88F1-E210D013720F} = {8A657AC5-150F-4F55-8D9E-4F1A56D62D60}
{C115C84A-AFCE-4796-A155-9CEE4C141938} = {8A657AC5-150F-4F55-8D9E-4F1A56D62D60}
{5336F099-DFF4-4439-9022-169AEB1FA737} = {802E669C-6885-4E60-9CFB-8CFB47EAF16A}
{0F64B74C-8869-4352-9AF5-A4BF0927BCF1} = {802E669C-6885-4E60-9CFB-8CFB47EAF16A}
{F33996A5-AAB6-4EC0-A865-E80AD16F3163} = {802E669C-6885-4E60-9CFB-8CFB47EAF16A}
EndGlobalSection
EndGlobal

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25123.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{4A5A60DD-41B6-40BF-B677-227A921ECCC8}"
ProjectSection(SolutionItems) = preProject
CommonAssemblyInfo.cs = CommonAssemblyInfo.cs
Npgsql.snk = Npgsql.snk
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{8537E50E-CF7F-49CB-B4EF-3E2A1B11F050}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{ED612DB1-AB32-4603-95E7-891BACA71C39}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Npgsql.EntityFrameworkCore.PostgreSQL", "src\Npgsql.EntityFrameworkCore.PostgreSQL\Npgsql.EntityFrameworkCore.PostgreSQL.csproj", "{FADDA2D1-03B4-4DEF-8D24-DD1CA4E81F4A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Npgsql.EntityFrameworkCore.PostgreSQL.Design", "src\Npgsql.EntityFrameworkCore.PostgreSQL.Design\Npgsql.EntityFrameworkCore.PostgreSQL.Design.csproj", "{8EDCED17-2D1D-45BE-9B61-0F715876DA94}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Npgsql.EntityFrameworkCore.PostgreSQL.Tests", "test\Npgsql.EntityFrameworkCore.PostgreSQL.Tests\Npgsql.EntityFrameworkCore.PostgreSQL.Tests.csproj", "{E1D99AD4-D88B-42BA-86DF-90B98B2E9A01}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Npgsql.EntityFrameworkCore.PostgreSQL.FunctionalTests", "test\Npgsql.EntityFrameworkCore.PostgreSQL.FunctionalTests\Npgsql.EntityFrameworkCore.PostgreSQL.FunctionalTests.csproj", "{05A7D0B7-4AE1-4BC8-A1BE-2389F1593B2D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Npgsql.EntityFrameworkCore.PostgreSQL.Design.FunctionalTests", "test\Npgsql.EntityFrameworkCore.PostgreSQL.Design.FunctionalTests\Npgsql.EntityFrameworkCore.PostgreSQL.Design.FunctionalTests.csproj", "{1410D291-C519-4E74-AE3D-6BC6C4A7C1DC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FADDA2D1-03B4-4DEF-8D24-DD1CA4E81F4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FADDA2D1-03B4-4DEF-8D24-DD1CA4E81F4A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FADDA2D1-03B4-4DEF-8D24-DD1CA4E81F4A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FADDA2D1-03B4-4DEF-8D24-DD1CA4E81F4A}.Release|Any CPU.Build.0 = Release|Any CPU
{8EDCED17-2D1D-45BE-9B61-0F715876DA94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8EDCED17-2D1D-45BE-9B61-0F715876DA94}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8EDCED17-2D1D-45BE-9B61-0F715876DA94}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8EDCED17-2D1D-45BE-9B61-0F715876DA94}.Release|Any CPU.Build.0 = Release|Any CPU
{E1D99AD4-D88B-42BA-86DF-90B98B2E9A01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E1D99AD4-D88B-42BA-86DF-90B98B2E9A01}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E1D99AD4-D88B-42BA-86DF-90B98B2E9A01}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E1D99AD4-D88B-42BA-86DF-90B98B2E9A01}.Release|Any CPU.Build.0 = Release|Any CPU
{05A7D0B7-4AE1-4BC8-A1BE-2389F1593B2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{05A7D0B7-4AE1-4BC8-A1BE-2389F1593B2D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{05A7D0B7-4AE1-4BC8-A1BE-2389F1593B2D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{05A7D0B7-4AE1-4BC8-A1BE-2389F1593B2D}.Release|Any CPU.Build.0 = Release|Any CPU
{1410D291-C519-4E74-AE3D-6BC6C4A7C1DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1410D291-C519-4E74-AE3D-6BC6C4A7C1DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1410D291-C519-4E74-AE3D-6BC6C4A7C1DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1410D291-C519-4E74-AE3D-6BC6C4A7C1DC}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{FADDA2D1-03B4-4DEF-8D24-DD1CA4E81F4A} = {8537E50E-CF7F-49CB-B4EF-3E2A1B11F050}
{8EDCED17-2D1D-45BE-9B61-0F715876DA94} = {8537E50E-CF7F-49CB-B4EF-3E2A1B11F050}
{E1D99AD4-D88B-42BA-86DF-90B98B2E9A01} = {ED612DB1-AB32-4603-95E7-891BACA71C39}
{05A7D0B7-4AE1-4BC8-A1BE-2389F1593B2D} = {ED612DB1-AB32-4603-95E7-891BACA71C39}
{1410D291-C519-4E74-AE3D-6BC6C4A7C1DC} = {ED612DB1-AB32-4603-95E7-891BACA71C39}
EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution
StartupItem = Npgsql.csproj
EndGlobalSection
EndGlobal
文件已添加
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageRestore>
<add key="automatic" value="False" />
</packageRestore>
<packageSources>
<add key="NuGet" value="https://api.nuget.org/v3/index.json" />
<add key="AspNetRelease" value="https://www.myget.org/F/aspnetrelease/api/v3/index.json" />
<add key="AspNetVNext" value="https://www.myget.org/F/aspnetcidev/api/v3/index.json" />
</packageSources>
</configuration>
Npgsql Entity Framework Core provider for PostgreSQL
=============
Npgsql.EntityFrameworkCore.PostgreSQL is an Entity Framework Core provider built on top of
[Npgsql](https://github.com/npgsql/npgsql). It allows you to use the EF Core ORM with
PostreSQL.
Note that beta packages are available for for dotnet RC1, and RC2 work is in progress.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Data.Entity.Scaffolding.Metadata;
namespace Microsoft.Data.Entity.Scaffolding.Metadata
{
class NpgsqlColumnModel : ColumnModel
{
/// <summary>
/// Identifies PostgreSQL serial columns.
/// These columns are configured with a default value coming from a specifically-named sequence.
/// </summary>
/// <remarks>
/// See http://www.postgresql.org/docs/current/static/datatype-numeric.html
/// </remarks>
public bool IsSerial { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Data.Entity.Scaffolding.Metadata;
namespace Microsoft.Data.Entity.Scaffolding.Metadata
{
public class NpgsqlIndexModel : IndexModel
{
/// <summary>
/// If the index contains an expression (rather than simple column references), the expression is contained here.
/// This is currently unsupported and will be ignored.
/// </summary>
public string Expression { get; set; }
}
}
<?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')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{8EDCED17-2D1D-45BE-9B61-0F715876DA94}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>EntityFramework7.Npgsql.Design</RootNamespace>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>..\..\Npgsql.snk</AssemblyOriginatorKeyFile>
<AssemblyName>Npgsql.EntityFrameworkCore.PostgreSQL.Design</AssemblyName>
<TargetFrameworkVersion>v4.6</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>DEBUG;TRACE</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</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="EntityFramework.Core, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\EntityFramework.Core.7.0.0-rc2-16583\lib\net451\EntityFramework.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="EntityFramework.Relational, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\EntityFramework.Relational.7.0.0-rc2-16583\lib\net451\EntityFramework.Relational.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="EntityFramework.Relational.Design, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\EntityFramework.Relational.Design.7.0.0-rc2-16583\lib\net451\EntityFramework.Relational.Design.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Extensions.Caching.Abstractions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Extensions.Caching.Abstractions.1.0.0-rc2-15948\lib\net451\Microsoft.Extensions.Caching.Abstractions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Extensions.Caching.Memory, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Extensions.Caching.Memory.1.0.0-rc2-15948\lib\net451\Microsoft.Extensions.Caching.Memory.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Extensions.Configuration, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Extensions.Configuration.1.0.0-rc1-final\lib\net451\Microsoft.Extensions.Configuration.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Extensions.Configuration.Abstractions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Extensions.Configuration.Abstractions.1.0.0-rc1-final\lib\net451\Microsoft.Extensions.Configuration.Abstractions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Extensions.Configuration.Binder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Extensions.Configuration.Binder.1.0.0-rc1-final\lib\net451\Microsoft.Extensions.Configuration.Binder.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Extensions.DependencyInjection, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Extensions.DependencyInjection.1.0.0-rc2-15888\lib\net451\Microsoft.Extensions.DependencyInjection.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.1.0.0-rc2-15888\lib\net451\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Extensions.Logging, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Extensions.Logging.1.0.0-rc2-15926\lib\net451\Microsoft.Extensions.Logging.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Extensions.Logging.Abstractions.1.0.0-rc2-15926\lib\net451\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Extensions.OptionsModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Extensions.OptionsModel.1.0.0-rc2-15904\lib\net451\Microsoft.Extensions.OptionsModel.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Extensions.Primitives, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Extensions.Primitives.1.0.0-rc2-15937\lib\net451\Microsoft.Extensions.Primitives.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Remotion.Linq, Version=2.0.0.0, Culture=neutral, PublicKeyToken=fee00910d6e5f53b, processorArchitecture=MSIL">
<HintPath>..\..\packages\Remotion.Linq.2.0.1\lib\net45\Remotion.Linq.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Collections.Concurrent" />
<Reference Include="System.Collections.Immutable, Version=1.1.36.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Collections.Immutable.1.1.36\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Core" />
<Reference Include="System.Diagnostics.DiagnosticSource, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Diagnostics.DiagnosticSource.4.0.0-rc2-23616\lib\dotnet5.2\System.Diagnostics.DiagnosticSource.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Interactive.Async, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Ix-Async.1.2.5\lib\net45\System.Interactive.Async.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Transactions" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Metadata\NpgsqlColumnModel.cs" />
<Compile Include="Metadata\NpgsqlIndexModel.cs" />
<Compile Include="NpgsqlDatabaseModelFactory.cs" />
<Compile Include="NpgsqlDesignTimeServices.cs" />
<Compile Include="NpgsqlScaffoldingModelFactory.cs" />
<Compile Include="NpgsqlTableSelectionSetExtensions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Utilities\Check.cs" />
<Compile Include="Utilities\LoggingExtensions.cs" />
<Compile Include="Utilities\SharedTypeExtensions.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Npgsql.EntityFrameworkCore.PostgreSQL\Npgsql.EntityFrameworkCore.PostgreSQL.csproj">
<Project>{fadda2d1-03b4-4def-8d24-dd1ca4e81f4a}</Project>
<Name>EntityFramework7.Npgsql</Name>
</ProjectReference>
<ProjectReference Include="..\Npgsql\Npgsql.csproj">
<Project>{9D13B739-62B1-4190-B386-7A9547304EB3}</Project>
<Name>Npgsql</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Analyzer Include="..\..\packages\Microsoft.CodeAnalysis.Analyzers.1.0.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.Analyzers.dll" />
<Analyzer Include="..\..\packages\Microsoft.CodeAnalysis.Analyzers.1.0.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.CSharp.Analyzers.dll" />
</ItemGroup>
<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>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0.24720" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.24720</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>c115c84a-afce-4796-a155-9cee4c141938</ProjectGuid>
<RootNamespace>EntityFramework7.Npgsql.Design</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using JetBrains.Annotations;
using Microsoft.Data.Entity.Metadata;
using Microsoft.Data.Entity.Migrations;
using Microsoft.Data.Entity.Migrations.Internal;
using Microsoft.Data.Entity.Scaffolding.Internal;
using Microsoft.Data.Entity.Scaffolding.Metadata;
using Microsoft.Data.Entity.Utilities;
using Microsoft.Extensions.Logging;
using Npgsql;
namespace Microsoft.Data.Entity.Scaffolding
{
public class NpgsqlDatabaseModelFactory : IDatabaseModelFactory
{
private NpgsqlConnection _connection;
private TableSelectionSet _tableSelectionSet;
private DatabaseModel _databaseModel;
private Dictionary<string, TableModel> _tables;
private Dictionary<string, NpgsqlColumnModel> _tableColumns;
private static string TableKey(TableModel table) => TableKey(table.Name, table.SchemaName);
private static string TableKey(string name, string schema) => $"\"{schema}\".\"{name}\"";
private static string ColumnKey(TableModel table, string columnName) => $"{TableKey(table)}.\"{columnName}\"";
public NpgsqlDatabaseModelFactory([NotNull] ILoggerFactory loggerFactory)
{
Check.NotNull(loggerFactory, nameof(loggerFactory));
Logger = loggerFactory.CreateCommandsLogger();
}
public virtual ILogger Logger { get; }
private void ResetState()
{
_connection = null;
_tableSelectionSet = null;
_databaseModel = new DatabaseModel();
_tables = new Dictionary<string, TableModel>();
_tableColumns = new Dictionary<string, NpgsqlColumnModel>(StringComparer.OrdinalIgnoreCase);
}
public DatabaseModel Create(string connectionString, TableSelectionSet tableSelectionSet)
{
Check.NotEmpty(connectionString, nameof(connectionString));
Check.NotNull(tableSelectionSet, nameof(tableSelectionSet));
ResetState();
using (_connection = new NpgsqlConnection(connectionString))
{
_connection.Open();
_tableSelectionSet = tableSelectionSet;
_databaseModel.DatabaseName = _connection.Database;
_databaseModel.DefaultSchemaName = "public";
GetTables();
GetColumns();
GetIndexes();
GetConstraints();
GetSequences();
return _databaseModel;
}
}
const string GetTablesQuery = @"
SELECT nspname, relname
FROM pg_class AS cl
JOIN pg_namespace AS ns ON ns.oid = cl.relnamespace
WHERE
cl.relkind = 'r' AND
ns.nspname NOT IN ('pg_catalog', 'information_schema') AND
relname <> '" + HistoryRepository.DefaultTableName + "'";
void GetTables()
{
using (var command = new NpgsqlCommand(GetTablesQuery, _connection))
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
var table = new TableModel
{
SchemaName = reader.GetString(0),
Name = reader.GetString(1)
};
if (_tableSelectionSet.Allows(table.SchemaName, table.Name))
{
_databaseModel.Tables.Add(table);
_tables[TableKey(table)] = table;
}
}
}
}
const string GetColumnsQuery = @"
SELECT
nspname, relname, attname, typname, attnum, atttypmod,
(NOT attnotnull) AS nullable,
CASE WHEN atthasdef THEN (SELECT pg_get_expr(adbin, cls.oid) FROM pg_attrdef WHERE adrelid = cls.oid AND adnum = attr.attnum) ELSE NULL END AS default
FROM pg_class AS cls
JOIN pg_namespace AS ns ON ns.oid = cls.relnamespace
LEFT OUTER JOIN pg_attribute AS attr ON attrelid = cls.oid
LEFT OUTER JOIN pg_type AS typ ON attr.atttypid = typ.oid
WHERE
atttypid <> 0 AND
relkind = 'r' AND
nspname NOT IN ('pg_catalog', 'information_schema') AND
relname <> '" + HistoryRepository.DefaultTableName + @"' AND
attnum > 0
ORDER BY attnum";
private void GetColumns()
{
using (var command = new NpgsqlCommand(GetColumnsQuery, _connection))
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
var schemaName = reader.GetString(0);
var tableName = reader.GetString(1);
if (!_tableSelectionSet.Allows(schemaName, tableName))
{
continue;
}
var columnName = reader.GetString(2);
var dataType = reader.GetString(3);
var ordinal = reader.GetInt32(4) - 1;
var typeModifier = reader.GetInt32(5);
var isNullable = reader.GetBoolean(6);
int? maxLength = null;
int? precision = null;
int? scale = null;
var defaultValue = reader.IsDBNull(7) ? null : reader.GetString(7);
if (typeModifier != -1)
{
switch (dataType)
{
case "bpchar":
case "char":
case "varchar":
maxLength = typeModifier - 4;
break;
case "numeric":
case "decimal":
// See http://stackoverflow.com/questions/3350148/where-are-numeric-precision-and-scale-for-a-field-found-in-the-pg-catalog-tables
precision = ((typeModifier - 4) >> 16) & 65535;
scale = (typeModifier - 4) & 65535;
break;
}
}
var table = _tables[TableKey(tableName, schemaName)];
var column = new NpgsqlColumnModel
{
Table = table,
Name = columnName,
DataType = dataType,
Ordinal = ordinal,
IsNullable = isNullable,
MaxLength = maxLength,
Precision = precision,
Scale = scale,
DefaultValue = defaultValue
};
// Somewhat hacky... We identify serial columns by examining their default expression,
// and reverse-engineer these as ValueGenerated.OnAdd
if (defaultValue != null && (
defaultValue == $"nextval('{tableName}_{columnName}_seq'::regclass)" ||
defaultValue == $"nextval('\"{tableName}_{columnName}_seq\"'::regclass)")
)
{
column.IsSerial = true;
column.ValueGenerated = ValueGenerated.OnAdd;
column.DefaultValue = null;
}
table.Columns.Add(column);
_tableColumns.Add(ColumnKey(table, column.Name), column);
}
}
}
const string GetIndexesQuery = @"
SELECT
nspname, cls.relname, idxcls.relname, indisunique, indkey,
CASE WHEN indexprs IS NULL THEN NULL ELSE pg_get_expr(indexprs, cls.oid) END
FROM pg_class AS cls
JOIN pg_namespace AS ns ON ns.oid = cls.relnamespace
JOIN pg_index AS idx ON indrelid = cls.oid
JOIN pg_class AS idxcls ON idxcls.oid = indexrelid
WHERE
cls.relkind = 'r' AND
nspname NOT IN ('pg_catalog', 'information_schema') AND
cls.relname <> '" + HistoryRepository.DefaultTableName + @"' AND
NOT indisprimary";
/// <remarks>
/// Primary keys are handled as in <see cref="GetConstraints"/>, not here
/// </remarks>
void GetIndexes()
{
using (var command = new NpgsqlCommand(GetIndexesQuery, _connection))
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
var schemaName = reader.GetString(0);
var tableName = reader.GetString(1);
var indexName = reader.GetString(2);
if (!_tableSelectionSet.Allows(schemaName, tableName))
{
continue;
}
TableModel table;
if (!_tables.TryGetValue(TableKey(tableName, schemaName), out table))
{
continue;
}
var index = new NpgsqlIndexModel
{
Table = table,
Name = indexName,
IsUnique = reader.GetBoolean(3)
};
table.Indexes.Add(index);
var columnIndices = reader.GetFieldValue<short[]>(4);
if (columnIndices.Any(i => i == 0))
{
if (reader.IsDBNull(5)) {
throw new Exception($"Seen 0 in indkey for index {indexName} but indexprs is null");
}
index.Expression = reader.GetString(5);
}
else foreach (var column in columnIndices.Select(i => table.Columns[i - 1]))
{
index.Columns.Add(column);
}
}
}
}
const string GetConstraintsQuery = @"
SELECT
ns.nspname, cls.relname, conname, contype, conkey, frnns.nspname, frncls.relname, confkey, confdeltype
FROM pg_class AS cls
JOIN pg_namespace AS ns ON ns.oid = cls.relnamespace
JOIN pg_constraint as con ON con.conrelid = cls.oid
LEFT OUTER JOIN pg_class AS frncls ON frncls.oid = con.confrelid
LEFT OUTER JOIN pg_namespace as frnns ON frnns.oid = frncls.relnamespace
WHERE
cls.relkind = 'r' AND
ns.nspname NOT IN ('pg_catalog', 'information_schema') AND
cls.relname <> '" + HistoryRepository.DefaultTableName + @"' AND
con.contype IN ('p', 'f')";
void GetConstraints()
{
using (var command = new NpgsqlCommand(GetConstraintsQuery, _connection))
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
var schemaName = reader.GetString(0);
var tableName = reader.GetString(1);
if (!_tableSelectionSet.Allows(schemaName, tableName))
{
continue;
}
var table = _tables[TableKey(tableName, schemaName)];
var constraintName = reader.GetString(2);
var constraintType = reader.GetChar(3);
switch (constraintType)
{
case 'p':
var pkColumnIndices = reader.GetFieldValue<short[]>(4);
for (var i = 0; i < pkColumnIndices.Length; i++)
{
table.Columns[pkColumnIndices[i] - 1].PrimaryKeyOrdinal = i + 1;
}
continue;
case 'f':
var foreignSchemaName = reader.GetString(5);
var foreignTableName = reader.GetString(6);
TableModel principalTable;
if (!_tables.TryGetValue(TableKey(foreignTableName, foreignSchemaName), out principalTable))
{
continue;
}
var fkInfo = new ForeignKeyModel
{
Name = constraintName,
Table = table,
PrincipalTable = principalTable,
OnDelete = ConvertToReferentialAction(reader.GetChar(8))
};
foreach (var column in reader.GetFieldValue<short[]>(4).Select(i => table.Columns[i - 1])) {
fkInfo.Columns.Add(column);
}
foreach (var principalColumn in reader.GetFieldValue<short[]>(7).Select(i => principalTable.Columns[i - 1])) {
fkInfo.PrincipalColumns.Add(principalColumn);
}
table.ForeignKeys.Add(fkInfo);
break;
default:
throw new NotSupportedException($"Unknown constraint type code {constraintType} for constraint {constraintName}");
}
}
}
}
static ReferentialAction? ConvertToReferentialAction(char onDeleteAction)
{
switch (onDeleteAction)
{
case 'a':
return ReferentialAction.NoAction;
case 'r':
return ReferentialAction.Restrict;
case 'c':
return ReferentialAction.Cascade;
case 'n':
return ReferentialAction.SetNull;
case 'd':
return ReferentialAction.SetDefault;
default:
throw new ArgumentOutOfRangeException($"Unknown value {onDeleteAction} for foreign key deletion action code");
}
}
const string GetSequencesQuery = @"
SELECT
sequence_schema, sequence_name, data_type, start_value::bigint, minimum_value::bigint, maximum_value::bigint, increment::int,
CASE WHEN cycle_option = 'YES' THEN TRUE ELSE FALSE END,
ownerns.nspname AS owner_schema,
tblcls.relname AS owner_table,
attname AS owner_column
FROM information_schema.sequences
JOIN pg_namespace AS seqns ON seqns.nspname = sequence_schema
JOIN pg_class AS seqcls ON seqcls.relnamespace = seqns.oid AND seqcls.relname = sequence_name AND seqcls.relkind = 'S'
LEFT OUTER JOIN pg_depend AS dep ON dep.objid = seqcls.oid AND deptype='a'
LEFT OUTER JOIN pg_class AS tblcls ON tblcls.oid = dep.refobjid
LEFT OUTER JOIN pg_attribute AS att ON attrelid = dep.refobjid AND attnum = dep.refobjsubid
LEFT OUTER JOIN pg_namespace AS ownerns ON ownerns.oid = tblcls.relnamespace";
void GetSequences()
{
using (var command = new NpgsqlCommand(GetSequencesQuery, _connection))
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
// If the sequence is OWNED BY a column which is a serial, we skip it. The sequence will be created implicitly.
if (!reader.IsDBNull(10))
{
var ownerSchema = reader.GetString(8);
var ownerTable = reader.GetString(9);
var ownerColumn = reader.GetString(10);
TableModel ownerTableModel;
NpgsqlColumnModel ownerColumnModel;
if (_tables.TryGetValue(TableKey(ownerTable, ownerSchema), out ownerTableModel) &&
_tableColumns.TryGetValue(ColumnKey(ownerTableModel, ownerColumn), out ownerColumnModel) &&
ownerColumnModel.IsSerial)
{
continue;
}
}
var sequence = new SequenceModel
{
SchemaName = reader.GetString(0),
Name = reader.GetString(1),
DataType = reader.GetString(2),
Start = reader.GetInt64(3),
Min = reader.GetInt64(4),
Max = reader.GetInt64(5),
IncrementBy = reader.GetInt32(6),
IsCyclic = reader.GetBoolean(7)
};
if (sequence.DataType == "bigint")
{
long defaultStart, defaultMin, defaultMax;
if (sequence.IncrementBy > 0)
{
defaultMin = 1;
defaultMax = long.MaxValue;
Debug.Assert(sequence.Min.HasValue);
defaultStart = sequence.Min.Value;
} else {
defaultMin = long.MinValue + 1;
defaultMax = -1;
Debug.Assert(sequence.Max.HasValue);
defaultStart = sequence.Max.Value;
}
if (sequence.Start == defaultStart) {
sequence.Start = null;
}
if (sequence.Min == defaultMin) {
sequence.Min = null;
}
if (sequence.Max == defaultMax) {
sequence.Max = null;
}
}
else
{
Logger.LogWarning($"Sequence with datatype {sequence.DataType} which isn't the expected bigint.");
}
_databaseModel.Sequences.Add(sequence);
}
}
}
}
}
using JetBrains.Annotations;
using Microsoft.Data.Entity.Metadata;
using Microsoft.Data.Entity.Scaffolding.Internal;
using Microsoft.Data.Entity.Storage;
using Microsoft.Data.Entity.Storage.Internal;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.Data.Entity.Scaffolding
{
public class NpgsqlDesignTimeServices
{
public virtual void ConfigureDesignTimeServices([NotNull] IServiceCollection serviceCollection)
{
serviceCollection
.AddSingleton<IScaffoldingModelFactory, NpgsqlScaffoldingModelFactory>()
.AddSingleton<IRelationalAnnotationProvider, NpgsqlAnnotationProvider>()
.AddSingleton<IRelationalTypeMapper, NpgsqlTypeMapper>()
.AddSingleton<IDatabaseModelFactory, NpgsqlDatabaseModelFactory>();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using Microsoft.Data.Entity.Internal;
using Microsoft.Data.Entity.Metadata;
using Microsoft.Data.Entity.Metadata.Builders;
using Microsoft.Data.Entity.Scaffolding.Internal;
using Microsoft.Data.Entity.Scaffolding.Metadata;
using Microsoft.Data.Entity.Storage;
using Microsoft.Data.Entity.Utilities;
using Microsoft.Extensions.Logging;
namespace Microsoft.Data.Entity.Scaffolding
{
public class NpgsqlScaffoldingModelFactory : RelationalScaffoldingModelFactory
{
public NpgsqlScaffoldingModelFactory(
[NotNull] ILoggerFactory loggerFactory,
[NotNull] IRelationalTypeMapper typeMapper,
[NotNull] IDatabaseModelFactory databaseModelFactory)
: base(loggerFactory, typeMapper, databaseModelFactory)
{
}
public override IModel Create(string connectionString, TableSelectionSet tableSelectionSet)
{
var model = base.Create(connectionString, tableSelectionSet);
model.Scaffolding().UseProviderMethodName = nameof(NpgsqlDbContextOptionsExtensions.UseNpgsql);
return model;
}
[CanBeNull]
protected override KeyBuilder VisitPrimaryKey(EntityTypeBuilder builder, TableModel table)
{
var keyBuilder = base.VisitPrimaryKey(builder, table);
if (keyBuilder == null)
{
return null;
}
// If this property is the single integer primary key on the EntityType then
// KeyConvention assumes ValueGeneratedOnAdd(). If the underlying column does
// not have Serial set then we need to set to ValueGeneratedNever() to
// override this behavior.
// TODO use KeyConvention directly to detect when it will be applied
var pkColumns = table.Columns.Where(c => c.PrimaryKeyOrdinal.HasValue).Cast<NpgsqlColumnModel>().ToList();
if (pkColumns.Count != 1 || pkColumns[0].IsSerial)
{
return keyBuilder;
}
// TODO
var property = builder.Metadata.FindProperty(GetPropertyName(pkColumns[0]));
var propertyType = property?.ClrType?.UnwrapNullableType();
if (propertyType?.IsIntegerForSerial() == true || propertyType == typeof(Guid))
{
property.ValueGenerated = ValueGenerated.Never;
}
return keyBuilder;
}
[CanBeNull]
protected override IndexBuilder VisitIndex(EntityTypeBuilder builder, IndexModel index)
{
var npgsqlIndex = (NpgsqlIndexModel)index;
if (npgsqlIndex.Expression != null)
{
Logger.LogWarning($"Ignoring unsupported index {index.Name} which contains an expression ({npgsqlIndex.Expression})");
return null;
}
return base.VisitIndex(builder, index);
}
}
}
using System.Linq;
using JetBrains.Annotations;
namespace Microsoft.Data.Entity.Scaffolding
{
internal static class NpgsqlTableSelectionSetExtensions
{
public static bool Allows(this TableSelectionSet _tableSelectionSet, [NotNull] string schemaName, [NotNull] string tableName)
{
if (_tableSelectionSet == null
|| (_tableSelectionSet.Schemas.Count == 0
&& _tableSelectionSet.Tables.Count == 0))
{
return true;
}
if (_tableSelectionSet.Schemas.Contains(schemaName))
{
return true;
}
return _tableSelectionSet.Tables.Contains($"{schemaName}.{tableName}")
|| _tableSelectionSet.Tables.Contains($"[{schemaName}].[{tableName}]")
|| _tableSelectionSet.Tables.Contains($"{schemaName}.[{tableName}]")
|| _tableSelectionSet.Tables.Contains($"[{schemaName}].{tableName}")
|| _tableSelectionSet.Tables.Contains($"{tableName}")
|| _tableSelectionSet.Tables.Contains($"[{tableName}]");
}
}
}
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("EntityFramework7.Npgsql.Design")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("EntityFramework7.Npgsql.Design")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("8edced17-2d1d-45be-9b61-0f715876da94")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using JetBrains.Annotations;
using Microsoft.Data.Entity.Internal;
namespace Microsoft.Data.Entity.Utilities
{
[DebuggerStepThrough]
internal static class Check
{
[ContractAnnotation("value:null => halt")]
public static T NotNull<T>([NoEnumeration] T value, [InvokerParameterName] [NotNull] string parameterName)
{
if (ReferenceEquals(value, null))
{
NotEmpty(parameterName, nameof(parameterName));
throw new ArgumentNullException(parameterName);
}
return value;
}
[ContractAnnotation("value:null => halt")]
public static T NotNull<T>(
[NoEnumeration] T value,
[InvokerParameterName] [NotNull] string parameterName,
[NotNull] string propertyName)
{
if (ReferenceEquals(value, null))
{
NotEmpty(parameterName, nameof(parameterName));
NotEmpty(propertyName, nameof(propertyName));
throw new ArgumentException(CoreStrings.ArgumentPropertyNull(propertyName, parameterName));
}
return value;
}
[ContractAnnotation("value:null => halt")]
public static IReadOnlyList<T> NotEmpty<T>(IReadOnlyList<T> value, [InvokerParameterName] [NotNull] string parameterName)
{
NotNull(value, parameterName);
if (value.Count == 0)
{
NotEmpty(parameterName, nameof(parameterName));
throw new ArgumentException(CoreStrings.CollectionArgumentIsEmpty(parameterName));
}
return value;
}
[ContractAnnotation("value:null => halt")]
public static string NotEmpty(string value, [InvokerParameterName] [NotNull] string parameterName)
{
Exception e = null;
if (ReferenceEquals(value, null))
{
e = new ArgumentNullException(parameterName);
}
else if (value.Trim().Length == 0)
{
e = new ArgumentException(CoreStrings.ArgumentIsEmpty(parameterName));
}
if (e != null)
{
NotEmpty(parameterName, nameof(parameterName));
throw e;
}
return value;
}
public static string NullButNotEmpty(string value, [InvokerParameterName] [NotNull] string parameterName)
{
if (!ReferenceEquals(value, null)
&& value.Length == 0)
{
NotEmpty(parameterName, nameof(parameterName));
throw new ArgumentException(CoreStrings.ArgumentIsEmpty(parameterName));
}
return value;
}
public static IReadOnlyList<T> HasNoNulls<T>(IReadOnlyList<T> value, [InvokerParameterName] [NotNull] string parameterName)
where T : class
{
NotNull(value, parameterName);
if (value.Any(e => e == null))
{
NotEmpty(parameterName, nameof(parameterName));
throw new ArgumentException(parameterName);
}
return value;
}
public static T IsDefined<T>(T value, [InvokerParameterName] [NotNull] string parameterName)
where T : struct
{
if (!Enum.IsDefined(typeof(T), value))
{
NotEmpty(parameterName, nameof(parameterName));
throw new ArgumentException(CoreStrings.InvalidEnumValue(parameterName, typeof(T)));
}
return value;
}
public static Type ValidEntityType(Type value, [InvokerParameterName] [NotNull] string parameterName)
{
if (!value.GetTypeInfo().IsClass)
{
NotEmpty(parameterName, nameof(parameterName));
throw new ArgumentException(CoreStrings.InvalidEntityType(parameterName, value));
}
return value;
}
}
}
namespace Microsoft.Extensions.Logging
{
internal static class LoggingExtensions
{
public const string CommandsLoggerName = "EntityFramework.Commands";
public static ILogger CreateCommandsLogger(this ILoggerFactory loggerFactory)
=> loggerFactory.CreateLogger(CommandsLoggerName);
public static ILogger CreateCommandsLogger(this ILoggerProvider loggerProvider)
=> loggerProvider.CreateLogger(CommandsLoggerName);
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Diagnostics;
using System.Linq;
using System.Reflection;
// ReSharper disable once CheckNamespace
namespace System
{
[DebuggerStepThrough]
internal static class SharedTypeExtensions
{
public static Type UnwrapNullableType(this Type type) => Nullable.GetUnderlyingType(type) ?? type;
public static bool IsNullableType(this Type type)
{
var typeInfo = type.GetTypeInfo();
return !typeInfo.IsValueType
|| (typeInfo.IsGenericType
&& typeInfo.GetGenericTypeDefinition() == typeof(Nullable<>));
}
public static Type MakeNullable(this Type type)
=> type.IsNullableType()
? type
: typeof(Nullable<>).MakeGenericType(type);
public static bool IsInteger(this Type type)
{
type = type.UnwrapNullableType();
return type == typeof(int)
|| type == typeof(long)
|| type == typeof(short)
|| type == typeof(byte)
|| type == typeof(uint)
|| type == typeof(ulong)
|| type == typeof(ushort)
|| type == typeof(sbyte);
}
public static bool IsIntegerForSerial(this Type type)
{
type = type.UnwrapNullableType();
return type == typeof(int)
|| type == typeof(long)
|| type == typeof(short);
}
public static PropertyInfo GetAnyProperty(this Type type, string name)
{
var props = type.GetRuntimeProperties().Where(p => p.Name == name).ToList();
if (props.Count() > 1)
{
throw new AmbiguousMatchException();
}
return props.SingleOrDefault();
}
private static bool IsNonIntegerPrimitive(this Type type)
{
type = type.UnwrapNullableType();
return type == typeof(bool)
|| type == typeof(byte[])
|| type == typeof(char)
|| type == typeof(DateTime)
|| type == typeof(DateTimeOffset)
|| type == typeof(decimal)
|| type == typeof(double)
|| type == typeof(float)
|| type == typeof(Guid)
|| type == typeof(string)
|| type == typeof(TimeSpan)
|| type.GetTypeInfo().IsEnum;
}
public static bool IsPrimitive(this Type type)
=> type.IsInteger()
|| type.IsNonIntegerPrimitive();
public static Type UnwrapEnumType(this Type type)
=> type.GetTypeInfo().IsEnum ? Enum.GetUnderlyingType(type) : type;
}
}
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.1.36.0" newVersion="1.1.36.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="EntityFramework.Core" version="7.0.0-rc2-16583" targetFramework="net46" />
<package id="EntityFramework.Relational" version="7.0.0-rc2-16583" targetFramework="net46" />
<package id="EntityFramework.Relational.Design" version="7.0.0-rc2-16583" targetFramework="net46" />
<package id="Ix-Async" version="1.2.5" targetFramework="net46" />
<package id="Microsoft.Extensions.Caching.Abstractions" version="1.0.0-rc2-15948" targetFramework="net46" />
<package id="Microsoft.Extensions.Caching.Memory" version="1.0.0-rc2-15948" targetFramework="net46" />
<package id="Microsoft.Extensions.Configuration" version="1.0.0-rc1-final" targetFramework="net46" />
<package id="Microsoft.Extensions.Configuration.Abstractions" version="1.0.0-rc1-final" targetFramework="net46" />
<package id="Microsoft.Extensions.Configuration.Binder" version="1.0.0-rc1-final" targetFramework="net46" />
<package id="Microsoft.Extensions.DependencyInjection" version="1.0.0-rc2-15888" targetFramework="net46" />
<package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="1.0.0-rc2-15888" targetFramework="net46" />
<package id="Microsoft.Extensions.Logging" version="1.0.0-rc2-15926" targetFramework="net46" />
<package id="Microsoft.Extensions.Logging.Abstractions" version="1.0.0-rc2-15926" targetFramework="net46" />
<package id="Microsoft.Extensions.OptionsModel" version="1.0.0-rc2-15904" targetFramework="net46" />
<package id="Microsoft.Extensions.Primitives" version="1.0.0-rc2-15937" targetFramework="net46" />
<package id="Remotion.Linq" version="2.0.1" targetFramework="net46" />
<package id="System.Collections.Immutable" version="1.1.36" targetFramework="net46" />
<package id="System.Diagnostics.DiagnosticSource" version="4.0.0-rc2-23616" targetFramework="net46" />
<package id="System.Diagnostics.Tracing" version="4.0.0" targetFramework="net46" />
<package id="System.Runtime" version="4.0.0" targetFramework="net46" />
<package id="System.Threading" version="4.0.0" targetFramework="net46" />
</packages>
\ No newline at end of file
{
"version": "3.1.0-*",
"authors": [
"Shay Rojansky"
],
"description": "Design-time Entity Framework Functionality for PostgreSQL",
"iconUrl": "http://www.npgsql.org/img/postgresql.gif",
"repository": {
"type": "git",
"url": "git://github.com/npgsql/npgsql"
},
"compilationOptions": {
"keyFile": "../../Npgsql.snk"
},
"dependencies" : {
"EntityFramework.Core": "7.0.0-rc2-16563",
"EntityFramework.Relational": "7.0.0-rc2-16563",
"EntityFramework.Relational.Design": "7.0.0-rc2-16563",
"Microsoft.Extensions.DependencyInjection": "1.0.0-rc2-*",
"Microsoft.Extensions.DependencyInjection.Abstractions": "1.0.0-rc2-*",
"EntityFramework7.Npgsql": "3.1.0-*",
"Npgsql": "3.1.0-*"
},
"frameworks": {
"net451": {
"frameworkAssemblies": {
"System.Collections": { "version": "4.0.0.0", "type": "build" },
"System.Reflection": { "version": "4.0.0.0", "type": "build" },
"System.Diagnostics.Contracts": { "version": "4.0.0.0", "type": "build" },
"System.Linq.Expressions": { "version": "4.0.0.0", "type": "build" },
"System.Runtime": { "version": "4.0.0.0", "type": "build" }
}
},
"dnx451": {
"frameworkAssemblies": {
"System.Collections": "4.0.0.0",
"System.Reflection": "4.0.0.0",
"System.Diagnostics.Contracts": "4.0.0.0",
"System.Linq.Expressions": "4.0.0.0",
"System.Runtime": "4.0.0.0"
}
},
"dotnet54": {
"dependencies": {
}
}
}
}
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Data.Common;
using JetBrains.Annotations;
using Microsoft.Data.Entity.Infrastructure;
using Microsoft.Data.Entity.Internal;
using Microsoft.Data.Entity.Utilities;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity
{
public static class NpgsqlDbContextOptionsExtensions
{
public static NpgsqlDbContextOptionsBuilder UseNpgsql([NotNull] this DbContextOptionsBuilder optionsBuilder, [NotNull] string connectionString)
{
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
Check.NotEmpty(connectionString, nameof(connectionString));
var extension = GetOrCreateExtension(optionsBuilder);
extension.ConnectionString = connectionString;
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
return new NpgsqlDbContextOptionsBuilder(optionsBuilder);
}
// Note: Decision made to use DbConnection not SqlConnection: Issue #772
public static NpgsqlDbContextOptionsBuilder UseNpgsql([NotNull] this DbContextOptionsBuilder optionsBuilder, [NotNull] DbConnection connection)
{
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
Check.NotNull(connection, nameof(connection));
var extension = GetOrCreateExtension(optionsBuilder);
extension.Connection = connection;
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
return new NpgsqlDbContextOptionsBuilder(optionsBuilder);
}
private static NpgsqlOptionsExtension GetOrCreateExtension(DbContextOptionsBuilder optionsBuilder)
{
var existing = optionsBuilder.Options.FindExtension<NpgsqlOptionsExtension>();
return existing != null
? new NpgsqlOptionsExtension(existing)
: new NpgsqlOptionsExtension();
}
}
}
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using JetBrains.Annotations;
using Microsoft.Data.Entity.Infrastructure;
using Microsoft.Data.Entity.Internal;
using Microsoft.Data.Entity.Metadata;
using Microsoft.Data.Entity.Metadata.Conventions.Internal;
using Microsoft.Data.Entity.Migrations;
using Microsoft.Data.Entity.Migrations.Internal;
using Microsoft.Data.Entity.Query.ExpressionTranslators.Internal;
using Microsoft.Data.Entity.Query.Internal;
using Microsoft.Data.Entity.Query.Sql.Internal;
using Microsoft.Data.Entity.Storage;
using Microsoft.Data.Entity.Storage.Internal;
using Microsoft.Data.Entity.Update.Internal;
using Microsoft.Data.Entity.Utilities;
using Microsoft.Data.Entity.ValueGeneration.Internal;
using Microsoft.Extensions.DependencyInjection.Extensions;
// ReSharper disable once CheckNamespace
namespace Microsoft.Extensions.DependencyInjection
{
public static class NpgsqlEntityFrameworkServicesBuilderExtensions
{
public static EntityFrameworkServicesBuilder AddNpgsql([NotNull] this EntityFrameworkServicesBuilder builder)
{
Check.NotNull(builder, nameof(builder));
var service = builder.AddRelational().GetInfrastructure();
service.TryAddEnumerable(ServiceDescriptor
.Singleton<IDatabaseProvider, DatabaseProvider<NpgsqlDatabaseProviderServices, NpgsqlOptionsExtension>>());
service.TryAdd(new ServiceCollection()
.AddSingleton<NpgsqlValueGeneratorCache>()
.AddSingleton<NpgsqlTypeMapper>()
.AddSingleton<NpgsqlSqlGenerationHelper>()
.AddSingleton<NpgsqlModelSource>()
.AddSingleton<NpgsqlAnnotationProvider>()
.AddSingleton<NpgsqlMigrationsAnnotationProvider>()
// TODO: NpgsqlModelValidator
.AddScoped<NpgsqlConventionSetBuilder>()
.AddScoped<NpgsqlUpdateSqlGenerator>()
.AddScoped<NpgsqlModificationCommandBatchFactory>()
.AddScoped<NpgsqlDatabaseProviderServices>()
.AddScoped<NpgsqlRelationalConnection>()
.AddScoped<NpgsqlMigrationsSqlGenerator>()
.AddScoped<NpgsqlDatabaseCreator>()
.AddScoped<NpgsqlHistoryRepository>()
.AddQuery());
return builder;
}
private static IServiceCollection AddQuery(this IServiceCollection serviceCollection)
{
return serviceCollection
.AddScoped<NpgsqlQueryCompilationContextFactory>()
.AddScoped<NpgsqlCompositeMemberTranslator>()
.AddScoped<NpgsqlCompositeMethodCallTranslator>()
.AddScoped<NpgsqlQuerySqlGeneratorFactory>();
}
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using JetBrains.Annotations;
using Microsoft.Data.Entity.Infrastructure;
using Microsoft.Data.Entity.Metadata.Builders;
using Microsoft.Data.Entity.Metadata.Internal;
using Microsoft.Data.Entity.Utilities;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity
{
public static class NpgsqlEntityTypeBuilderExtensions
{
public static EntityTypeBuilder ForNpgsqlToTable(
[NotNull] this EntityTypeBuilder entityTypeBuilder,
[CanBeNull] string name)
{
Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));
Check.NullButNotEmpty(name, nameof(name));
var relationalEntityTypeBuilder = ((IInfrastructure<InternalEntityTypeBuilder>)entityTypeBuilder).GetInfrastructure()
.Npgsql(ConfigurationSource.Explicit);
relationalEntityTypeBuilder.TableName = name;
return entityTypeBuilder;
}
public static EntityTypeBuilder<TEntity> ForNpgsqlToTable<TEntity>(
[NotNull] this EntityTypeBuilder<TEntity> entityTypeBuilder,
[CanBeNull] string name)
where TEntity : class
=> (EntityTypeBuilder<TEntity>)ForNpgsqlToTable((EntityTypeBuilder)entityTypeBuilder, name);
public static EntityTypeBuilder ForNpgsqlToTable(
[NotNull] this EntityTypeBuilder entityTypeBuilder,
[CanBeNull] string name,
[CanBeNull] string schema)
{
Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));
Check.NullButNotEmpty(name, nameof(name));
Check.NullButNotEmpty(schema, nameof(schema));
var relationalEntityTypeBuilder = ((IInfrastructure<InternalEntityTypeBuilder>)entityTypeBuilder).GetInfrastructure()
.Npgsql(ConfigurationSource.Explicit);
relationalEntityTypeBuilder.TableName = name;
relationalEntityTypeBuilder.Schema = schema;
return entityTypeBuilder;
}
public static EntityTypeBuilder<TEntity> ForNpgsqlToTable<TEntity>(
[NotNull] this EntityTypeBuilder<TEntity> entityTypeBuilder,
[CanBeNull] string name,
[CanBeNull] string schema)
where TEntity : class
=> (EntityTypeBuilder<TEntity>)ForNpgsqlToTable((EntityTypeBuilder)entityTypeBuilder, name, schema);
}
}
using JetBrains.Annotations;
using Microsoft.Data.Entity.Metadata;
using Microsoft.Data.Entity.Metadata.Internal;
using Microsoft.Data.Entity.Utilities;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity
{
public static class NpgsqlMetadataExtensions
{
public static IRelationalEntityTypeAnnotations Npgsql([NotNull] this IEntityType entityType)
=> new RelationalEntityTypeAnnotations(Check.NotNull(entityType, nameof(entityType)), NpgsqlAnnotationNames.Prefix);
public static RelationalEntityTypeAnnotations Npgsql([NotNull] this EntityType entityType)
=> (RelationalEntityTypeAnnotations)Npgsql((IEntityType)entityType);
public static IRelationalForeignKeyAnnotations Npgsql([NotNull] this IForeignKey foreignKey)
=> new RelationalForeignKeyAnnotations(Check.NotNull(foreignKey, nameof(foreignKey)), NpgsqlAnnotationNames.Prefix);
public static RelationalForeignKeyAnnotations Npgsql([NotNull] this ForeignKey foreignKey)
=> (RelationalForeignKeyAnnotations)Npgsql((IForeignKey)foreignKey);
public static NpgsqlIndexAnnotations Npgsql([NotNull] this IIndex index)
=> new NpgsqlIndexAnnotations(Check.NotNull(index, nameof(index)));
public static RelationalIndexAnnotations Npgsql([NotNull] this Index index)
=> Npgsql((IIndex)index);
public static IRelationalKeyAnnotations Npgsql([NotNull] this IKey key)
=> new RelationalKeyAnnotations(Check.NotNull(key, nameof(key)), NpgsqlAnnotationNames.Prefix);
public static RelationalKeyAnnotations Npgsql([NotNull] this Key key)
=> (RelationalKeyAnnotations)Npgsql((IKey)key);
public static RelationalModelAnnotations Npgsql([NotNull] this Model model)
=> (RelationalModelAnnotations)Npgsql((IModel)model);
public static IRelationalModelAnnotations Npgsql([NotNull] this IModel model)
=> new RelationalModelAnnotations(Check.NotNull(model, nameof(model)), NpgsqlAnnotationNames.Prefix);
public static IRelationalPropertyAnnotations Npgsql([NotNull] this IProperty property)
=> new RelationalPropertyAnnotations(Check.NotNull(property, nameof(property)), NpgsqlAnnotationNames.Prefix);
public static RelationalPropertyAnnotations Npgsql([NotNull] this Property property)
=> (RelationalPropertyAnnotations)Npgsql((IProperty)property);
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using JetBrains.Annotations;
using Microsoft.Data.Entity.Internal;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Infrastructure
{
public class NpgsqlDbContextOptionsBuilder : RelationalDbContextOptionsBuilder<NpgsqlDbContextOptionsBuilder, NpgsqlOptionsExtension>
{
public NpgsqlDbContextOptionsBuilder([NotNull] DbContextOptionsBuilder optionsBuilder)
: base(optionsBuilder)
{
}
protected override NpgsqlOptionsExtension CloneExtension()
=> new NpgsqlOptionsExtension(OptionsBuilder.Options.GetExtension<NpgsqlOptionsExtension>());
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using JetBrains.Annotations;
using Microsoft.Data.Entity.Infrastructure;
using Microsoft.Data.Entity.Metadata.Conventions.Internal;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Internal
{
public class NpgsqlModelSource : ModelSource
{
public NpgsqlModelSource(
[NotNull] IDbSetFinder setFinder,
[NotNull] ICoreConventionSetBuilder coreConventionSetBuilder)
: base(setFinder, coreConventionSetBuilder)
{
}
}
}
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using JetBrains.Annotations;
using Microsoft.Data.Entity.Infrastructure;
using Microsoft.Data.Entity.Utilities;
using Microsoft.Extensions.DependencyInjection;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Internal
{
public class NpgsqlOptionsExtension : RelationalOptionsExtension
{
public NpgsqlOptionsExtension()
{
}
public NpgsqlOptionsExtension([NotNull] NpgsqlOptionsExtension copyFrom)
: base(copyFrom)
{
}
public override void ApplyServices(EntityFrameworkServicesBuilder builder)
{
Check.NotNull(builder, nameof(builder));
builder.AddNpgsql();
}
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// ReSharper disable once CheckNamespace
using JetBrains.Annotations;
using Microsoft.Data.Entity.Storage;
namespace Microsoft.Data.Entity.Metadata.Conventions.Internal
{
public class NpgsqlConventionSetBuilder : RelationalConventionSetBuilder
{
public NpgsqlConventionSetBuilder([NotNull] IRelationalTypeMapper typeMapper)
: base(typeMapper)
{
}
// TODO: SqlServer has identity here, do we need something?
}
}
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.Data.Entity.Metadata
{
public interface INpgsqlPropertyAnnotations : IRelationalPropertyAnnotations
{
string SequenceName { get; }
string SequenceSchema { get; }
Sequence TryGetSequence();
}
}
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Metadata.Internal
{
public static class NpgsqlAnnotationNames
{
public const string Prefix = "Npgsql:";
public const string Serial = "Serial";
public const string DefaultSequenceName = "DefaultSequenceName";
public const string DefaultSequenceSchema = "DefaultSequenceSchema";
public const string SequenceName = "SequenceName";
public const string SequenceSchema = "SequenceSchema";
public const string IndexMethod = "IndexMethod";
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using JetBrains.Annotations;
namespace Microsoft.Data.Entity.Metadata.Internal
{
public static class NpgsqlInternalMetadataBuilderExtensions
{
public static RelationalEntityTypeBuilderAnnotations Npgsql(
[NotNull] this InternalEntityTypeBuilder builder,
ConfigurationSource configurationSource)
=> new RelationalEntityTypeBuilderAnnotations(builder, configurationSource, NpgsqlAnnotationNames.Prefix);
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.Data.Entity.Metadata
{
public class NpgsqlAnnotationProvider : IRelationalAnnotationProvider
{
public virtual IRelationalEntityTypeAnnotations For(IEntityType entityType) => entityType.Npgsql();
public virtual IRelationalForeignKeyAnnotations For(IForeignKey foreignKey) => foreignKey.Npgsql();
public virtual IRelationalIndexAnnotations For(IIndex index) => index.Npgsql();
public virtual IRelationalKeyAnnotations For(IKey key) => key.Npgsql();
public virtual IRelationalModelAnnotations For(IModel model) => model.Npgsql();
public virtual IRelationalPropertyAnnotations For(IProperty property) => property.Npgsql();
}
}
using JetBrains.Annotations;
using Microsoft.Data.Entity.Metadata.Internal;
namespace Microsoft.Data.Entity.Metadata
{
public class NpgsqlIndexAnnotations : RelationalIndexAnnotations
{
public NpgsqlIndexAnnotations([NotNull] IIndex index)
: base(index, NpgsqlAnnotationNames.Prefix)
{
}
protected NpgsqlIndexAnnotations([NotNull] RelationalAnnotations annotations)
: base(annotations)
{
}
/// <summary>
/// The PostgreSQL index method to be used. Null selects the default (currently btree).
/// </summary>
/// <remarks>
/// http://www.postgresql.org/docs/current/static/sql-createindex.html
/// </remarks>
public string Method
{
get { return (string) Annotations.GetAnnotation(NpgsqlAnnotationNames.IndexMethod); }
set { Annotations.SetAnnotation(NpgsqlAnnotationNames.IndexMethod, value); }
}
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Text;
using JetBrains.Annotations;
using Microsoft.Data.Entity.Infrastructure;
using Microsoft.Data.Entity.Metadata;
using Microsoft.Data.Entity.Storage;
using Microsoft.Data.Entity.Storage.Internal;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Migrations.Internal
{
public class NpgsqlHistoryRepository : HistoryRepository
{
public NpgsqlHistoryRepository(
[NotNull] IDatabaseCreator databaseCreator,
[NotNull] IRawSqlCommandBuilder rawSqlCommandBuilder,
[NotNull] NpgsqlRelationalConnection connection,
[NotNull] IDbContextOptions options,
[NotNull] IMigrationsModelDiffer modelDiffer,
[NotNull] IMigrationsSqlGenerator migrationsSqlGenerator,
[NotNull] IRelationalAnnotationProvider annotations,
[NotNull] ISqlGenerationHelper sqlGenerationHelper)
: base(
databaseCreator,
rawSqlCommandBuilder,
connection,
options,
modelDiffer,
migrationsSqlGenerator,
annotations,
sqlGenerationHelper)
{
}
protected override string ExistsSql
{
get
{
var builder = new StringBuilder();
builder.Append("SELECT EXISTS (SELECT 1 FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid=c.relnamespace WHERE ");
if (TableSchema != null)
{
builder
.Append("n.nspname='")
.Append(SqlGenerationHelper.EscapeLiteral(TableSchema))
.Append("' AND ");
}
builder
.Append("c.relname='")
.Append(SqlGenerationHelper.EscapeLiteral(TableName))
.Append("');");
return builder.ToString();
}
}
protected override bool InterpretExistsResult(object value) => (bool)value;
public override string GetCreateIfNotExistsScript()
{
return GetCreateScript();
}
public override string GetBeginIfNotExistsScript(string migrationId)
{
throw new NotSupportedException("Generating idempotent scripts for migration is not currently supported by Npgsql");
}
public override string GetBeginIfExistsScript(string migrationId)
{
throw new NotSupportedException("Generating idempotent scripts for migration is not currently supported by Npgsql");
}
public override string GetEndIfScript()
{
throw new NotSupportedException("Generating idempotent scripts for migration is not currently supported by Npgsql");
}
}
}
using System;
using System.Collections.Generic;
using Microsoft.Data.Entity.Infrastructure;
using Microsoft.Data.Entity.Metadata;
using Microsoft.Data.Entity.Metadata.Internal;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Migrations.Internal
{
public class NpgsqlMigrationsAnnotationProvider : MigrationsAnnotationProvider
{
public override IEnumerable<IAnnotation> For(IProperty property)
{
if (property.ValueGenerated == ValueGenerated.OnAdd &&
property.ClrType.IsIntegerForSerial()) {
yield return new Annotation(NpgsqlAnnotationNames.Prefix + NpgsqlAnnotationNames.Serial, true);
}
// TODO: Named sequences
// TODO: We don't support ValueGenerated.OnAddOrUpdate, so should we throw an exception?
// Other providers don't seem to...
}
public override IEnumerable<IAnnotation> For(IIndex index)
{
if (index.Npgsql().Method != null)
{
yield return new Annotation(
NpgsqlAnnotationNames.Prefix + NpgsqlAnnotationNames.IndexMethod,
index.Npgsql().Method);
}
}
}
}
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Linq;
using JetBrains.Annotations;
using Microsoft.Data.Entity.Infrastructure;
using Microsoft.Data.Entity.Metadata;
using Microsoft.Data.Entity.Metadata.Internal;
using Microsoft.Data.Entity.Migrations.Operations;
using Microsoft.Data.Entity.Storage;
using Microsoft.Data.Entity.Storage.Internal;
using Microsoft.Data.Entity.Update;
using Microsoft.Data.Entity.Utilities;
namespace Microsoft.Data.Entity.Migrations
{
public class NpgsqlMigrationsSqlGenerator : MigrationsSqlGenerator
{
public NpgsqlMigrationsSqlGenerator(
[NotNull] IRelationalCommandBuilderFactory commandBuilderFactory,
[NotNull] ISqlGenerationHelper sqlGenerationHelper,
[NotNull] IRelationalTypeMapper typeMapper,
[NotNull] IRelationalAnnotationProvider annotations)
: base(commandBuilderFactory, sqlGenerationHelper, typeMapper, annotations)
{
}
protected override void Generate(MigrationOperation operation, IModel model, RelationalCommandListBuilder builder)
{
Check.NotNull(operation, nameof(operation));
Check.NotNull(builder, nameof(builder));
var createDatabaseOperation = operation as NpgsqlCreateDatabaseOperation;
var dropDatabaseOperation = operation as NpgsqlDropDatabaseOperation;
if (createDatabaseOperation != null)
{
Generate(createDatabaseOperation, model, builder);
}
else if (dropDatabaseOperation != null)
{
Generate(dropDatabaseOperation, model, builder);
}
else
{
base.Generate(operation, model, builder);
}
}
protected override void Generate(AlterColumnOperation operation, IModel model, RelationalCommandListBuilder builder)
{
Check.NotNull(operation, nameof(operation));
Check.NotNull(builder, nameof(builder));
// TODO: There is probably duplication here with other methods. See ColumnDefinition.
//TODO: this should provide feature parity with the EF6 provider, check if there's anything missing for EF7
var type = operation.ColumnType;
if (operation.ColumnType == null)
{
var property = FindProperty(model, operation.Schema, operation.Table, operation.Name);
type = property != null
? TypeMapper.GetMapping(property).DefaultTypeName
: TypeMapper.GetMapping(operation.ClrType).DefaultTypeName;
}
var serial = operation.FindAnnotation(NpgsqlAnnotationNames.Prefix + NpgsqlAnnotationNames.Serial);
var isSerial = serial != null && (bool)serial.Value;
var identifier = SqlGenerationHelper.DelimitIdentifier(operation.Table, operation.Schema);
var alterBase = $"ALTER TABLE {identifier} ALTER COLUMN {SqlGenerationHelper.DelimitIdentifier(operation.Name)}";
// TYPE
builder.Append(alterBase)
.Append(" TYPE ")
.Append(type)
.AppendLine(SqlGenerationHelper.StatementTerminator);
// NOT NULL
builder.Append(alterBase)
.Append(operation.IsNullable ? " DROP NOT NULL" : " SET NOT NULL")
.AppendLine(SqlGenerationHelper.StatementTerminator);
builder.Append(alterBase);
if (operation.DefaultValue != null)
{
builder.Append(" SET DEFAULT ")
.Append(SqlGenerationHelper.GenerateLiteral((dynamic)operation.DefaultValue))
.AppendLine(SqlGenerationHelper.StatementTerminator);
}
else if (!string.IsNullOrWhiteSpace(operation.DefaultValueSql))
{
builder.Append(" SET DEFAULT ")
.Append(operation.DefaultValueSql)
.AppendLine(SqlGenerationHelper.StatementTerminator);
}
else if (isSerial)
{
builder.Append(" SET DEFAULT ");
switch (type)
{
case "smallint":
case "int":
case "bigint":
case "real":
case "double precision":
case "numeric":
//TODO: need function CREATE SEQUENCE IF NOT EXISTS and set to it...
//Until this is resolved changing IsIdentity from false to true
//on types int2, int4 and int8 won't switch to type serial2, serial4 and serial8
throw new NotImplementedException("Not supporting creating sequence for integer types");
case "uuid":
builder.Append("uuid_generate_v4()");
break;
default:
throw new NotImplementedException($"Not supporting creating IsIdentity for {type}");
}
}
else
{
builder.Append(" DROP DEFAULT ");
}
}
protected override void Generate(CreateSequenceOperation operation, IModel model, RelationalCommandListBuilder builder)
{
Check.NotNull(operation, nameof(operation));
Check.NotNull(builder, nameof(builder));
if (operation.ClrType != typeof(long))
{
throw new NotSupportedException("PostgreSQL sequences can only be bigint (long)");
}
builder
.Append("CREATE SEQUENCE ")
.Append(SqlGenerationHelper.DelimitIdentifier(operation.Name, operation.Schema));
builder
.Append(" START WITH ")
.Append(SqlGenerationHelper.GenerateLiteral(operation.StartValue));
SequenceOptions(operation, model, builder);
}
protected override void Generate(RenameIndexOperation operation, IModel model, RelationalCommandListBuilder builder)
{
Check.NotNull(operation, nameof(operation));
Check.NotNull(builder, nameof(builder));
if (operation.NewName != null)
{
Rename(operation.Schema, operation.Name, operation.NewName, "INDEX", builder);
}
}
protected override void Generate(RenameSequenceOperation operation, IModel model, RelationalCommandListBuilder builder)
{
Check.NotNull(operation, nameof(operation));
Check.NotNull(builder, nameof(builder));
var separate = false;
var name = operation.Name;
if (operation.NewName != null)
{
Rename(operation.Schema, operation.Name, operation.NewName, "SEQUENCE", builder);
separate = true;
name = operation.NewName;
}
if (operation.NewSchema != null)
{
if (separate)
{
builder.AppendLine(SqlGenerationHelper.StatementTerminator);
}
Transfer(operation.NewSchema, operation.Schema, name, "SEQUENCE", builder);
}
}
protected override void Generate(RenameTableOperation operation, IModel model, RelationalCommandListBuilder builder)
{
Check.NotNull(operation, nameof(operation));
Check.NotNull(builder, nameof(builder));
var separate = false;
var name = operation.Name;
if (operation.NewName != null)
{
Rename(operation.Schema, operation.Name, operation.NewName, "TABLE", builder);
separate = true;
name = operation.NewName;
}
if (operation.NewSchema != null)
{
if (separate)
{
builder.AppendLine(SqlGenerationHelper.StatementTerminator);
}
Transfer(operation.NewSchema, operation.Schema, name, "TABLE", builder);
}
}
protected override void Generate(
[NotNull] CreateIndexOperation operation,
[CanBeNull] IModel model,
[NotNull] RelationalCommandListBuilder builder)
{
Check.NotNull(operation, nameof(operation));
Check.NotNull(builder, nameof(builder));
var method = (string)operation[NpgsqlAnnotationNames.Prefix + NpgsqlAnnotationNames.IndexMethod];
builder.Append("CREATE ");
if (operation.IsUnique)
{
builder.Append("UNIQUE ");
}
builder
.Append("INDEX ")
.Append(SqlGenerationHelper.DelimitIdentifier(operation.Name))
.Append(" ON ")
.Append(SqlGenerationHelper.DelimitIdentifier(operation.Table, operation.Schema));
if (method != null)
{
builder
.Append(" USING ")
.Append(method);
}
builder
.Append(" (")
.Append(ColumnList(operation.Columns))
.Append(")");
}
protected override void Generate(EnsureSchemaOperation operation, IModel model, RelationalCommandListBuilder builder)
{
Check.NotNull(operation, nameof(operation));
Check.NotNull(builder, nameof(builder));
// PostgreSQL 9.2 and below unfortunately doesn't have CREATE SCHEMA IF NOT EXISTS.
// An attempted workaround by creating a function which checks and creates the schema, and then invoking it, failed because
// of #641 (pg_temp doesn't exist yet).
// So the only workaround for pre-9.3 PostgreSQL, at least for now, is to define all tables in the public schema.
// NOTE: Technically the public schema can be dropped so we should also be ensuring it, but this is a rare case and
// we want to allow pre-9.3
if (operation.Name == "public") {
return;
}
builder
.Append("CREATE SCHEMA IF NOT EXISTS ")
.Append(SqlGenerationHelper.DelimitIdentifier(operation.Name))
.AppendLine(SqlGenerationHelper.StatementTerminator);
}
public virtual void Generate(NpgsqlCreateDatabaseOperation operation, IModel model, RelationalCommandListBuilder builder)
{
Check.NotNull(operation, nameof(operation));
Check.NotNull(builder, nameof(builder));
builder
.Append("CREATE DATABASE ")
.Append(SqlGenerationHelper.DelimitIdentifier(operation.Name))
.AppendLine(SqlGenerationHelper.StatementTerminator);
}
public virtual void Generate(NpgsqlDropDatabaseOperation operation, IModel model, RelationalCommandListBuilder builder)
{
Check.NotNull(operation, nameof(operation));
Check.NotNull(builder, nameof(builder));
var dbName = SqlGenerationHelper.DelimitIdentifier(operation.Name);
builder
// TODO: The following revokes connection only for the public role, what about other connecting roles?
.Append("REVOKE CONNECT ON DATABASE ")
.Append(dbName)
.Append(" FROM PUBLIC")
.AppendLine(SqlGenerationHelper.StatementTerminator)
// TODO: For PG <= 9.1, the column name is prodpic, not pid (see http://stackoverflow.com/questions/5408156/how-to-drop-a-postgresql-database-if-there-are-active-connections-to-it)
.Append(
"SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = '")
.Append(operation.Name)
.Append("'")
.AppendLine(SqlGenerationHelper.StatementTerminator)
.Append("DROP DATABASE ")
.Append(dbName);
}
protected override void Generate(DropIndexOperation operation, IModel model, RelationalCommandListBuilder builder)
{
Check.NotNull(operation, nameof(operation));
Check.NotNull(builder, nameof(builder));
builder
.Append("DROP INDEX ")
.Append(SqlGenerationHelper.DelimitIdentifier(operation.Name, operation.Schema));
}
protected override void Generate(
[NotNull] RenameColumnOperation operation,
[CanBeNull] IModel model,
[NotNull] RelationalCommandListBuilder builder)
{
Check.NotNull(operation, nameof(operation));
Check.NotNull(builder, nameof(builder));
builder.Append("ALTER TABLE ")
.Append(SqlGenerationHelper.DelimitIdentifier(operation.Table, operation.Schema))
.Append(" RENAME COLUMN ")
.Append(SqlGenerationHelper.DelimitIdentifier(operation.Name))
.Append(" TO ")
.Append(SqlGenerationHelper.DelimitIdentifier(operation.NewName));
}
protected override void ColumnDefinition(
string schema,
string table,
string name,
Type clrType,
string type,
bool nullable,
object defaultValue,
string defaultValueSql,
string computedColumnSql,
IAnnotatable annotatable,
IModel model,
RelationalCommandListBuilder builder)
{
Check.NotEmpty(name, nameof(name));
Check.NotNull(annotatable, nameof(annotatable));
Check.NotNull(clrType, nameof(clrType));
Check.NotNull(builder, nameof(builder));
if (type == null)
{
var property = FindProperty(model, schema, table, name);
type = property != null
? TypeMapper.GetMapping(property).DefaultTypeName
: TypeMapper.GetMapping(clrType).DefaultTypeName;
}
// TODO: Maybe implement computed columns via functions?
// http://stackoverflow.com/questions/11165450/store-common-query-as-column/11166268#11166268
var serial = annotatable[NpgsqlAnnotationNames.Prefix + NpgsqlAnnotationNames.Serial];
if (serial != null && (bool)serial)
{
switch (type)
{
case "int":
case "int4":
type = "serial";
break;
case "bigint":
case "int8":
type = "bigserial";
break;
case "smallint":
case "int2":
type = "smallserial";
break;
default:
throw new InvalidOperationException($"Column {name} of type {type} can't be Identity");
}
}
base.ColumnDefinition(
schema,
table,
name,
clrType,
type,
nullable,
defaultValue,
defaultValueSql,
computedColumnSql,
annotatable,
model,
builder);
}
public virtual void Rename(
[CanBeNull] string schema,
[NotNull] string name,
[NotNull] string newName,
[NotNull] string type,
[NotNull] RelationalCommandListBuilder builder)
{
Check.NotEmpty(name, nameof(name));
Check.NotEmpty(newName, nameof(newName));
Check.NotEmpty(type, nameof(type));
Check.NotNull(builder, nameof(builder));
builder
.Append("ALTER ")
.Append(type)
.Append(" ")
.Append(SqlGenerationHelper.DelimitIdentifier(name, schema))
.Append(" RENAME TO ")
.Append(SqlGenerationHelper.DelimitIdentifier(newName));
}
public virtual void Transfer(
[NotNull] string newSchema,
[CanBeNull] string schema,
[NotNull] string name,
[NotNull] string type,
[NotNull] RelationalCommandListBuilder builder)
{
Check.NotEmpty(newSchema, nameof(newSchema));
Check.NotEmpty(name, nameof(name));
Check.NotNull(type, nameof(type));
Check.NotNull(builder, nameof(builder));
builder
.Append("ALTER ")
.Append(type)
.Append(" ")
.Append(SqlGenerationHelper.DelimitIdentifier(name, schema))
.Append(" SET SCHEMA ")
.Append(SqlGenerationHelper.DelimitIdentifier(newSchema));
}
protected override void ForeignKeyAction(ReferentialAction referentialAction, RelationalCommandListBuilder builder)
{
Check.NotNull(builder, nameof(builder));
if (referentialAction == ReferentialAction.Restrict)
{
builder.Append("NO ACTION");
}
else
{
base.ForeignKeyAction(referentialAction, builder);
}
}
string ColumnList(string[] columns) => string.Join(", ", columns.Select(SqlGenerationHelper.DelimitIdentifier));
}
}
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using JetBrains.Annotations;
namespace Microsoft.Data.Entity.Migrations.Operations
{
public class NpgsqlCreateDatabaseOperation : MigrationOperation
{
public virtual string Name { get;[param: NotNull] set; }
}
}
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using JetBrains.Annotations;
namespace Microsoft.Data.Entity.Migrations.Operations
{
public class NpgsqlDropDatabaseOperation : MigrationOperation
{
public virtual string Name { get;[param: NotNull] set; }
}
}
<?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')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{FADDA2D1-03B4-4DEF-8D24-DD1CA4E81F4A}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Npgsql.EntityFrameworkCore.PostgreSQL</RootNamespace>
<AssemblyName>Npgsql.EntityFrameworkCore.PostgreSQL</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>..\..\Npgsql.snk</AssemblyOriginatorKeyFile>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Debug\Npgsql.EntityFrameworkCore.PostgreSQL.xml</DocumentationFile>
<NoWarn>1591</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Release\Npgsql.EntityFrameworkCore.PostgreSQL.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="EntityFramework.Core, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\EntityFramework.Core.7.0.0-rc2-16583\lib\net451\EntityFramework.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="EntityFramework.Relational, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\EntityFramework.Relational.7.0.0-rc2-16583\lib\net451\EntityFramework.Relational.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Extensions.Caching.Abstractions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Extensions.Caching.Abstractions.1.0.0-rc2-15948\lib\net451\Microsoft.Extensions.Caching.Abstractions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Extensions.Caching.Memory, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Extensions.Caching.Memory.1.0.0-rc2-15948\lib\net451\Microsoft.Extensions.Caching.Memory.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Extensions.Configuration, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Extensions.Configuration.1.0.0-rc1-final\lib\net451\Microsoft.Extensions.Configuration.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Extensions.Configuration.Abstractions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Extensions.Configuration.Abstractions.1.0.0-rc1-final\lib\net451\Microsoft.Extensions.Configuration.Abstractions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Extensions.Configuration.Binder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Extensions.Configuration.Binder.1.0.0-rc1-final\lib\net451\Microsoft.Extensions.Configuration.Binder.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Extensions.DependencyInjection, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Extensions.DependencyInjection.1.0.0-rc2-15888\lib\net451\Microsoft.Extensions.DependencyInjection.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.1.0.0-rc2-15888\lib\net451\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Extensions.Logging, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Extensions.Logging.1.0.0-rc2-15926\lib\net451\Microsoft.Extensions.Logging.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Extensions.Logging.Abstractions.1.0.0-rc2-15926\lib\net451\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Extensions.OptionsModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Extensions.OptionsModel.1.0.0-rc2-15904\lib\net451\Microsoft.Extensions.OptionsModel.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Extensions.Primitives, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Extensions.Primitives.1.0.0-rc2-15937\lib\net451\Microsoft.Extensions.Primitives.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Remotion.Linq, Version=2.0.0.0, Culture=neutral, PublicKeyToken=fee00910d6e5f53b, processorArchitecture=MSIL">
<HintPath>..\..\packages\Remotion.Linq.2.0.1\lib\net45\Remotion.Linq.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Collections.Concurrent" />
<Reference Include="System.Collections.Immutable, Version=1.1.36.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Collections.Immutable.1.1.36\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Core" />
<Reference Include="System.Diagnostics.DiagnosticSource, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Diagnostics.DiagnosticSource.4.0.0-rc2-23616\lib\dotnet5.2\System.Diagnostics.DiagnosticSource.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Interactive.Async, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Ix-Async.1.2.5\lib\net45\System.Interactive.Async.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Transactions" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Extensions\NpgsqlEntityTypeBuilderExtensions.cs" />
<Compile Include="Infrastructure\NpgsqlDbContextOptionsBuilder.cs" />
<Compile Include="Extensions\NpgsqlDbContextOptionsExtensions.cs" />
<Compile Include="Extensions\NpgsqlEntityFrameworkServicesBuilderExtensions.cs" />
<Compile Include="Metadata\INpgsqlPropertyAnnotations.cs" />
<Compile Include="Metadata\Internal\NpgsqlAnnotationNames.cs" />
<Compile Include="Metadata\Internal\NpgsqlInternalMetadataBuilderExtensions.cs" />
<Compile Include="Metadata\NpgsqlIndexAnnotations.cs" />
<Compile Include="Metadata\NpgsqlAnnotationProvider.cs" />
<Compile Include="Migrations\Operations\NpgsqlCreateDatabaseOperation.cs" />
<Compile Include="Migrations\Operations\NpgsqlDropDatabaseOperation.cs" />
<Compile Include="Migrations\Internal\NpgsqlHistoryRepository.cs" />
<Compile Include="Migrations\Internal\NpgsqlMigrationsAnnotationProvider.cs" />
<Compile Include="Migrations\NpgsqlMigrationsSqlGenerator.cs" />
<Compile Include="Query\ExpressionTranslators\Internal\NpgsqlCompositeMemberTranslator.cs" />
<Compile Include="Query\ExpressionTranslators\Internal\NpgsqlCompositeMethodCallTranslator.cs" />
<Compile Include="Metadata\Conventions\Internal\NpgsqlConventionSetBuilder.cs" />
<Compile Include="Storage\Internal\NpgsqlSqlGenerationHelper.cs" />
<Compile Include="Storage\Internal\NpgsqlRelationalConnection.cs" />
<Compile Include="Storage\Internal\NpgsqlDatabaseCreator.cs" />
<Compile Include="Storage\Internal\NpgsqlDatabaseProviderServices.cs" />
<Compile Include="Extensions\NpgsqlMetadataExtensions.cs" />
<Compile Include="Internal\NpgsqlModelSource.cs" />
<Compile Include="Internal\NpgsqlOptionsExtension.cs" />
<Compile Include="Storage\Internal\NpgsqlTypeMapper.cs" />
<Compile Include="Storage\Internal\NpgsqlTypeMapping.cs" />
<Compile Include="Update\Internal\NpgsqlUpdateSqlGenerator.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="..\CommonAssemblyInfo.cs">
<Link>Properties\CommonAssemblyInfo.cs</Link>
<SubType>Code</SubType>
</Compile>
<Compile Include="Query\Expressions\Internal\AtTimeZoneExpression.cs" />
<Compile Include="Query\Expressions\Internal\RegexMatchExpression.cs" />
<Compile Include="Query\ExpressionTranslators\Internal\NpgsqlDateTimeNowTranslator.cs" />
<Compile Include="Query\ExpressionTranslators\Internal\NpgsqlMathAbsTranslator.cs" />
<Compile Include="Query\ExpressionTranslators\Internal\NpgsqlMathCeilingTranslator.cs" />
<Compile Include="Query\ExpressionTranslators\Internal\NpgsqlMathFloorTranslator.cs" />
<Compile Include="Query\ExpressionTranslators\Internal\NpgsqlMathPowerTranslator.cs" />
<Compile Include="Query\ExpressionTranslators\Internal\NpgsqlMathRoundTranslator.cs" />
<Compile Include="Query\ExpressionTranslators\Internal\NpgsqlMathTruncateTranslator.cs" />
<Compile Include="Query\ExpressionTranslators\Internal\NpgsqlRegexIsMatchTranslator.cs" />
<Compile Include="Query\ExpressionTranslators\Internal\NpgsqlStringLengthTranslator.cs" />
<Compile Include="Query\ExpressionTranslators\Internal\NpgsqlStringReplaceTranslator.cs" />
<Compile Include="Query\ExpressionTranslators\Internal\NpgsqlStringSubstringTranslator.cs" />
<Compile Include="Query\ExpressionTranslators\Internal\NpgsqlStringToLowerTranslator.cs" />
<Compile Include="Query\ExpressionTranslators\Internal\NpgsqlStringToUpperTranslator.cs" />
<Compile Include="Query\Internal\NpgsqlQueryCompilationContext.cs" />
<Compile Include="Query\Internal\NpgsqlQueryCompilationContextFactory.cs" />
<Compile Include="Query\Sql\Internal\NpgsqlQuerySqlGenerator.cs" />
<Compile Include="Query\Sql\Internal\NpgsqlQuerySqlGeneratorFactory.cs" />
<Compile Include="Update\Internal\NpgsqlModificationCommandBatch.cs" />
<Compile Include="Update\Internal\NpgsqlModificationCommandBatchFactory.cs" />
<Compile Include="Utilities\AsyncEnumerableExtensions.cs" />
<Compile Include="Utilities\Check.cs" />
<Compile Include="Utilities\EnumerableExtensions.cs" />
<Compile Include="Utilities\SharedTypeExtensions.cs" />
<Compile Include="Utilities\StringBuilderExtensions.cs" />
<Compile Include="ValueGeneration\Internal\NpgsqlValueGeneratorCache.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Npgsql\Npgsql.csproj">
<Project>{9d13b739-62b1-4190-b386-7a9547304eb3}</Project>
<Name>Npgsql</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<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>
<?xml version="1.0"?>
<package xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<metadata xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<id>EntityFramework7.Npgsql</id>
<title>Npgsql for Entity Framework 7</title>
<version>3.1.0-beta7-1</version>
<authors>Shay Rojansky</authors>
<owners>Shay Rojansky</owners>
<licenseUrl>https://github.com/npgsql/npgsql/blob/develop/LICENSE.txt</licenseUrl>
<projectUrl>http://www.npgsql.org</projectUrl>
<copyright>Copyright 2002 - 2016 Npgsql Development Team</copyright>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>PostgreSQL provider for Entity Framework 7</description>
<summary>PostgreSQL provider for Entity Framework 7</summary>
<language>en-US</language>
<tags>npgsql postgresql postgres data database entity framework ef orm</tags>
<dependencies>
<dependency id="Npgsql" version="[3.1.0-alpha1]" />
<dependency id="EntityFramework.Relational" version="[7.0.0-beta7]" />
</dependencies>
</metadata>
<files>
<file src="bin\Release\EntityFramework7.Npgsql.dll" target="lib\net45"/>
<file src="bin\Release\EntityFramework7.Npgsql.pdb" target="lib\net45"/>
<file src="bin\Release\EntityFramework7.Npgsql.xml" target="lib\net45"/>
<file src="**\*.cs" target="src" />
</files>
</package>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" 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)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>0f7e25eb-e266-477a-88f1-e210d013720f</ProjectGuid>
<RootNamespace>EntityFramework7.Npgsql</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>
\ No newline at end of file
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Reflection;
using System.Resources;
using Microsoft.Data.Entity.Infrastructure;
[assembly: AssemblyTitle("EntityFramework7.Npgsql")]
[assembly: AssemblyDescription("PostgreSQL provider for Entity Framework 7")]
[assembly: DesignTimeProviderServices(
fullyQualifiedTypeName: "Microsoft.Data.Entity.Scaffolding.NpgsqlDesignTimeServices, EntityFramework7.Npgsql.Design",
packageName: "EntityFramework7.Npgsql.Design")]
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Query.ExpressionTranslators.Internal
{
public class NpgsqlCompositeMemberTranslator : RelationalCompositeMemberTranslator
{
public NpgsqlCompositeMemberTranslator()
{
var npgsqlTranslators = new List<IMemberTranslator>
{
new NpgsqlStringLengthTranslator(),
new NpgsqlDateTimeNowTranslator()
};
AddTranslators(npgsqlTranslators);
}
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using JetBrains.Annotations;
using Microsoft.Extensions.Logging;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Query.ExpressionTranslators.Internal
{
public class NpgsqlCompositeMethodCallTranslator : RelationalCompositeMethodCallTranslator
{
private static readonly IMethodCallTranslator[] _methodCallTranslators =
{
new NpgsqlStringSubstringTranslator(),
new NpgsqlMathAbsTranslator(),
new NpgsqlMathCeilingTranslator(),
new NpgsqlMathFloorTranslator(),
new NpgsqlMathPowerTranslator(),
new NpgsqlMathRoundTranslator(),
new NpgsqlMathTruncateTranslator(),
new NpgsqlStringReplaceTranslator(),
new NpgsqlStringToLowerTranslator(),
new NpgsqlStringToUpperTranslator(),
new NpgsqlRegexIsMatchTranslator(),
};
public NpgsqlCompositeMethodCallTranslator([NotNull] ILogger<NpgsqlCompositeMethodCallTranslator> logger)
: base(logger)
{
// ReSharper disable once DoNotCallOverridableMethodsInConstructor
AddTranslators(_methodCallTranslators);
}
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Linq.Expressions;
using JetBrains.Annotations;
using Microsoft.Data.Entity.Query.Expressions;
using Microsoft.Data.Entity.Query.Expressions.Internal;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Query.ExpressionTranslators.Internal
{
public class NpgsqlDateTimeNowTranslator : IMemberTranslator
{
public virtual Expression Translate([NotNull] MemberExpression memberExpression)
{
if (memberExpression.Expression == null
&& memberExpression.Member.DeclaringType == typeof(DateTime))
{
if (memberExpression.Member.Name == nameof(DateTime.Now))
{
return new SqlFunctionExpression("NOW", memberExpression.Type);
}
else if (memberExpression.Member.Name == nameof(DateTime.UtcNow))
{
return new AtTimeZoneExpression(new SqlFunctionExpression("NOW", memberExpression.Type), "UTC");
}
}
return null;
}
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Query.ExpressionTranslators.Internal
{
public class NpgsqlMathAbsTranslator : MultipleOverloadStaticMethodCallTranslator
{
public NpgsqlMathAbsTranslator()
: base(typeof(Math), "Abs", "ABS")
{
}
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Query.ExpressionTranslators.Internal
{
public class NpgsqlMathCeilingTranslator : MultipleOverloadStaticMethodCallTranslator
{
public NpgsqlMathCeilingTranslator()
: base(typeof(Math), "Ceiling", "CEILING")
{
}
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Query.ExpressionTranslators.Internal
{
public class NpgsqlMathFloorTranslator : MultipleOverloadStaticMethodCallTranslator
{
public NpgsqlMathFloorTranslator()
: base(typeof(Math), "Floor", "FLOOR")
{
}
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Query.ExpressionTranslators.Internal
{
public class NpgsqlMathPowerTranslator : SingleOverloadStaticMethodCallTranslator
{
public NpgsqlMathPowerTranslator()
: base(typeof(Math), "Pow", "POWER")
{
}
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using JetBrains.Annotations;
using Microsoft.Data.Entity.Query.Expressions;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Query.ExpressionTranslators.Internal
{
public class NpgsqlMathRoundTranslator : IMethodCallTranslator
{
private static IEnumerable<MethodInfo> _methodInfos = typeof(Math).GetTypeInfo().GetDeclaredMethods(nameof(Math.Round))
.Where(m => m.GetParameters().Count() == 1
|| (m.GetParameters().Count() == 2 && m.GetParameters()[1].ParameterType == typeof(int)));
public virtual Expression Translate([NotNull] MethodCallExpression methodCallExpression)
{
if (_methodInfos.Contains(methodCallExpression.Method))
{
var arguments = methodCallExpression.Arguments.Count == 1
? new[] { methodCallExpression.Arguments[0], Expression.Constant(0) }
: new[] { methodCallExpression.Arguments[1], methodCallExpression.Arguments[1] };
return new SqlFunctionExpression("ROUND", methodCallExpression.Type, arguments);
}
return null;
}
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using JetBrains.Annotations;
using Microsoft.Data.Entity.Query.Expressions;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Query.ExpressionTranslators.Internal
{
public class NpgsqlMathTruncateTranslator : IMethodCallTranslator
{
private static readonly IEnumerable<MethodInfo> _methodInfos = typeof(Math).GetTypeInfo().GetDeclaredMethods(nameof(Math.Truncate));
public virtual Expression Translate([NotNull] MethodCallExpression methodCallExpression)
{
if (_methodInfos.Contains(methodCallExpression.Method))
{
return new SqlFunctionExpression("TRUNC", methodCallExpression.Type, new[] { methodCallExpression.Arguments[0] });
}
return null;
}
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text.RegularExpressions;
using JetBrains.Annotations;
using Microsoft.Data.Entity.Query.Expressions;
using Microsoft.Data.Entity.Query.Expressions.Internal;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Query.ExpressionTranslators.Internal
{
/// <summary>
/// Translates Regex.IsMatch calls into PostgreSQL regex expressions for database-side processing.
/// </summary>
/// <remarks>
/// http://www.postgresql.org/docs/current/static/functions-matching.html
/// </remarks>
public class NpgsqlRegexIsMatchTranslator : IMethodCallTranslator
{
static readonly MethodInfo IsMatch;
static readonly MethodInfo IsMatchWithRegexOptions;
const RegexOptions UnsupportedRegexOptions = RegexOptions.RightToLeft | RegexOptions.ECMAScript;
static NpgsqlRegexIsMatchTranslator()
{
IsMatch = typeof (Regex).GetTypeInfo().GetDeclaredMethods("IsMatch").Single(m =>
m.GetParameters().Count() == 2 &&
m.GetParameters().All(p => p.ParameterType == typeof(string))
);
IsMatchWithRegexOptions = typeof(Regex).GetTypeInfo().GetDeclaredMethods("IsMatch").Single(m =>
m.GetParameters().Count() == 3 &&
m.GetParameters().Take(2).All(p => p.ParameterType == typeof(string)) &&
m.GetParameters()[2].ParameterType == typeof(RegexOptions)
);
}
public Expression Translate([NotNull] MethodCallExpression methodCallExpression)
{
// Regex.IsMatch(string, string)
if (methodCallExpression.Method == IsMatch)
{
return new RegexMatchExpression(
methodCallExpression.Arguments[0],
methodCallExpression.Arguments[1],
RegexOptions.None
);
}
// Regex.IsMatch(string, string, RegexOptions)
if (methodCallExpression.Method == IsMatchWithRegexOptions)
{
var constantExpr = methodCallExpression.Arguments[2] as ConstantExpression;
if (constantExpr == null)
{
return null;
}
var options = (RegexOptions) constantExpr.Value;
if ((options & UnsupportedRegexOptions) != 0)
{
return null;
}
return new RegexMatchExpression(
methodCallExpression.Arguments[0],
methodCallExpression.Arguments[1],
options
);
}
return null;
}
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Linq.Expressions;
using JetBrains.Annotations;
using Microsoft.Data.Entity.Query.Expressions;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Query.ExpressionTranslators.Internal
{
public class NpgsqlStringLengthTranslator : IMemberTranslator
{
public virtual Expression Translate([NotNull] MemberExpression memberExpression)
{
if (memberExpression.Expression != null
&& memberExpression.Expression.Type == typeof(string)
&& memberExpression.Member.Name == "Length")
{
return new SqlFunctionExpression("LENGTH", memberExpression.Type, new[] { memberExpression.Expression });
}
return null;
}
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using JetBrains.Annotations;
using Microsoft.Data.Entity.Query.Expressions;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Query.ExpressionTranslators.Internal
{
public class NpgsqlStringReplaceTranslator : IMethodCallTranslator
{
private static readonly MethodInfo _methodInfo = typeof(string).GetTypeInfo().GetDeclaredMethods(nameof(string.Replace))
.Where(m => m.GetParameters()[0].ParameterType == typeof(string))
.Single();
public virtual Expression Translate([NotNull] MethodCallExpression methodCallExpression)
{
if (methodCallExpression.Method == _methodInfo)
{
var sqlArguments = new[] { methodCallExpression.Object }.Concat(methodCallExpression.Arguments);
return new SqlFunctionExpression("REPLACE", methodCallExpression.Type, sqlArguments);
}
return null;
}
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using JetBrains.Annotations;
using Microsoft.Data.Entity.Query.Expressions;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Query.ExpressionTranslators.Internal
{
public class NpgsqlStringSubstringTranslator : IMethodCallTranslator
{
private static readonly MethodInfo _methodInfo = typeof(string).GetTypeInfo().GetDeclaredMethods(nameof(string.Substring))
.Where(m => m.GetParameters().Count() == 2)
.Single();
public virtual Expression Translate([NotNull] MethodCallExpression methodCallExpression)
{
if (methodCallExpression.Method == _methodInfo)
{
var sqlArguments = new[] { methodCallExpression.Object }.Concat(methodCallExpression.Arguments);
return new SqlFunctionExpression("SUBSTRING", methodCallExpression.Type, sqlArguments);
}
return null;
}
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Query.ExpressionTranslators.Internal
{
public class NpgsqlStringToLowerTranslator : ParameterlessInstanceMethodCallTranslator
{
public NpgsqlStringToLowerTranslator()
: base(declaringType: typeof(string), clrMethodName: "ToLower", sqlFunctionName: "LOWER")
{
}
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Query.ExpressionTranslators.Internal
{
public class NpgsqlStringToUpperTranslator : ParameterlessInstanceMethodCallTranslator
{
public NpgsqlStringToUpperTranslator()
: base(declaringType: typeof(string), clrMethodName: "ToUpper", sqlFunctionName: "UPPER")
{
}
}
}
using System;
using System.Linq.Expressions;
using JetBrains.Annotations;
using Microsoft.Data.Entity.Query.Sql.Internal;
using Microsoft.Data.Entity.Utilities;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Query.Expressions.Internal
{
public class AtTimeZoneExpression : Expression
{
public AtTimeZoneExpression([NotNull] Expression timestampExpression, [NotNull] string timeZone)
{
Check.NotNull(timestampExpression, nameof(timestampExpression));
Check.NotNull(timeZone, nameof(timeZone));
TimestampExpression = timestampExpression;
TimeZone = timeZone;
}
public Expression TimestampExpression { get; }
public string TimeZone { get; }
public override ExpressionType NodeType => ExpressionType.Extension;
public override Type Type => typeof(DateTime);
protected override Expression Accept([NotNull] ExpressionVisitor visitor)
{
Check.NotNull(visitor, nameof(visitor));
var specificVisitor = visitor as NpgsqlQuerySqlGenerator;
return specificVisitor != null
? specificVisitor.VisitAtTimeZone(this)
: base.Accept(visitor);
}
protected override Expression VisitChildren(ExpressionVisitor visitor)
{
var newTimestampExpression = visitor.Visit(TimestampExpression);
return newTimestampExpression != TimestampExpression
? new AtTimeZoneExpression(newTimestampExpression, TimeZone)
: this;
}
public override string ToString() => $"{TimestampExpression} AT TIME ZONE {TimeZone}";
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Linq.Expressions;
using System.Text.RegularExpressions;
using JetBrains.Annotations;
using Microsoft.Data.Entity.Query.Sql;
using Microsoft.Data.Entity.Query.Sql.Internal;
using Microsoft.Data.Entity.Utilities;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Query.Expressions.Internal
{
public class RegexMatchExpression : Expression
{
public RegexMatchExpression([NotNull] Expression match, [NotNull] Expression pattern, RegexOptions options)
{
Check.NotNull(match, nameof(match));
Check.NotNull(pattern, nameof(pattern));
Match = match;
Pattern = pattern;
Options = options;
}
public Expression Match { get; }
public Expression Pattern { get; }
public RegexOptions Options { get; }
public override ExpressionType NodeType => ExpressionType.Extension;
public override Type Type => typeof(bool);
protected override Expression Accept([NotNull] ExpressionVisitor visitor)
{
Check.NotNull(visitor, nameof(visitor));
var specificVisitor = visitor as NpgsqlQuerySqlGenerator;
return specificVisitor != null
? specificVisitor.VisitRegexMatch(this)
: base.Accept(visitor);
}
protected override Expression VisitChildren(ExpressionVisitor visitor)
{
var newMatchExpression = visitor.Visit(Match);
var newPatternExpression = visitor.Visit(Pattern);
return newMatchExpression != Match
|| newPatternExpression != Pattern
? new RegexMatchExpression(newMatchExpression, newPatternExpression, Options)
: this;
}
public override string ToString() => $"{Match} ~ {Pattern}";
}
}
using System;
using JetBrains.Annotations;
using Microsoft.Data.Entity.Infrastructure;
using Microsoft.Data.Entity.Metadata;
using Microsoft.Data.Entity.Query.ExpressionVisitors;
using Microsoft.Data.Entity.Utilities;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Query.Internal
{
public class NpgsqlQueryCompilationContext : RelationalQueryCompilationContext
{
public NpgsqlQueryCompilationContext(
[NotNull] IModel model,
[NotNull] ISensitiveDataLogger logger,
[NotNull] IEntityQueryModelVisitorFactory entityQueryModelVisitorFactory,
[NotNull] IRequiresMaterializationExpressionVisitorFactory requiresMaterializationExpressionVisitorFactory,
[NotNull] ILinqOperatorProvider linqOpeartorProvider,
[NotNull] IQueryMethodProvider queryMethodProvider,
[NotNull] Type contextType,
bool trackQueryResults)
: base(
Check.NotNull(model, nameof(model)),
Check.NotNull(logger, nameof(logger)),
Check.NotNull(entityQueryModelVisitorFactory, nameof(entityQueryModelVisitorFactory)),
Check.NotNull(requiresMaterializationExpressionVisitorFactory, nameof(requiresMaterializationExpressionVisitorFactory)),
Check.NotNull(linqOpeartorProvider, nameof(linqOpeartorProvider)),
Check.NotNull(queryMethodProvider, nameof(queryMethodProvider)),
Check.NotNull(contextType, nameof(contextType)),
trackQueryResults)
{
}
public override bool IsLateralJoinSupported => true;
}
}
using JetBrains.Annotations;
using Microsoft.Data.Entity.Infrastructure;
using Microsoft.Data.Entity.Metadata;
using Microsoft.Data.Entity.Query.ExpressionVisitors;
using Microsoft.Data.Entity.Utilities;
using Remotion.Linq.Parsing.Structure.NodeTypeProviders;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Query.Internal
{
public class NpgsqlQueryCompilationContextFactory : RelationalQueryCompilationContextFactory
{
public NpgsqlQueryCompilationContextFactory(
[NotNull] IModel model,
[NotNull] ISensitiveDataLogger<NpgsqlQueryCompilationContextFactory> logger,
[NotNull] IEntityQueryModelVisitorFactory entityQueryModelVisitorFactory,
[NotNull] IRequiresMaterializationExpressionVisitorFactory requiresMaterializationExpressionVisitorFactory,
[NotNull] MethodInfoBasedNodeTypeRegistry methodInfoBasedNodeTypeRegistry,
[NotNull] DbContext context)
: base(
Check.NotNull(model, nameof(model)),
Check.NotNull(logger, nameof(logger)),
Check.NotNull(entityQueryModelVisitorFactory, nameof(entityQueryModelVisitorFactory)),
Check.NotNull(requiresMaterializationExpressionVisitorFactory, nameof(requiresMaterializationExpressionVisitorFactory)),
Check.NotNull(methodInfoBasedNodeTypeRegistry, nameof(methodInfoBasedNodeTypeRegistry)),
Check.NotNull(context, nameof(context)))
{
}
public override QueryCompilationContext Create(bool async)
=> async
? new NpgsqlQueryCompilationContext(
Model,
(ISensitiveDataLogger)Logger,
EntityQueryModelVisitorFactory,
RequiresMaterializationExpressionVisitorFactory,
new AsyncLinqOperatorProvider(),
new AsyncQueryMethodProvider(),
ContextType,
TrackQueryResults)
: new NpgsqlQueryCompilationContext(
Model,
(ISensitiveDataLogger)Logger,
EntityQueryModelVisitorFactory,
RequiresMaterializationExpressionVisitorFactory,
new LinqOperatorProvider(),
new QueryMethodProvider(),
ContextType,
TrackQueryResults);
}
}
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Linq.Expressions;
using System.Text.RegularExpressions;
using JetBrains.Annotations;
using Microsoft.Data.Entity.Query.Expressions;
using Microsoft.Data.Entity.Query.Expressions.Internal;
using Microsoft.Data.Entity.Storage;
using Microsoft.Data.Entity.Utilities;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Query.Sql.Internal
{
public class NpgsqlQuerySqlGenerator : DefaultQuerySqlGenerator
{
protected override string ConcatOperator => "||";
protected override string TrueLiteral => "TRUE";
protected override string FalseLiteral => "FALSE";
protected override string TypedTrueLiteral => "TRUE::bool";
protected override string TypedFalseLiteral => "FALSE::bool";
public NpgsqlQuerySqlGenerator(
[NotNull] IRelationalCommandBuilderFactory relationalCommandBuilderFactory,
[NotNull] ISqlGenerationHelper sqlGenerationHelper,
[NotNull] IParameterNameGeneratorFactory parameterNameGeneratorFactory,
[NotNull] IRelationalTypeMapper relationalTypeMapper,
[NotNull] SelectExpression selectExpression)
: base(
relationalCommandBuilderFactory,
sqlGenerationHelper,
parameterNameGeneratorFactory,
relationalTypeMapper,
selectExpression)
{
}
protected override void GenerateTop([NotNull]SelectExpression selectExpression)
{
// No TOP() in PostgreSQL, see GenerateLimitOffset
}
protected override void GenerateLimitOffset([NotNull] SelectExpression selectExpression)
{
Check.NotNull(selectExpression, nameof(selectExpression));
if (selectExpression.Limit != null)
{
Sql.AppendLine().Append("LIMIT ");
Visit(selectExpression.Limit);
}
if (selectExpression.Offset != null)
{
if (selectExpression.Limit == null) {
Sql.AppendLine();
} else {
Sql.Append(' ');
}
Sql.Append("OFFSET ");
Visit(selectExpression.Offset);
}
}
public override Expression VisitCount(CountExpression countExpression)
{
Check.NotNull(countExpression, nameof(countExpression));
// Note that PostgreSQL COUNT(*) is BIGINT (64-bit). For 32-bit Count() expressions we cast.
if (countExpression.Type == typeof(long))
{
Sql.Append("COUNT(*)");
}
else if (countExpression.Type == typeof(int))
{
Sql.Append("COUNT(*)::INT4");
}
else throw new NotSupportedException($"Count expression with type {countExpression.Type} not supported");
return countExpression;
}
public override Expression VisitSum(SumExpression sumExpression)
{
base.VisitSum(sumExpression);
// In PostgreSQL SUM() doesn't return the same type as its argument for smallint, int and bigint.
// Cast to get the same type.
// http://www.postgresql.org/docs/current/static/functions-aggregate.html
if (sumExpression.Type == typeof(short))
{
Sql.Append("::INT2");
}
else if (sumExpression.Type == typeof (int))
{
Sql.Append("::INT4");
}
else if (sumExpression.Type == typeof(long))
{
Sql.Append("::INT8");
}
return sumExpression;
}
protected override Expression VisitBinary(BinaryExpression binaryExpression)
{
// PostgreSQL 9.4 and below has some weird operator precedence fixed in 9.5 and described here:
// http://git.postgresql.org/gitweb/?p=postgresql.git&a=commitdiff&h=c6b3c939b7e0f1d35f4ed4996e71420a993810d2
// As a result we must surround string concatenation with parentheses
if (binaryExpression.NodeType == ExpressionType.Add &&
binaryExpression.Left.Type == typeof (string) &&
binaryExpression.Right.Type == typeof (string))
{
Sql.Append("(");
var exp = base.VisitBinary(binaryExpression);
Sql.Append(")");
return exp;
}
return base.VisitBinary(binaryExpression);
}
// See http://www.postgresql.org/docs/current/static/functions-matching.html
public Expression VisitRegexMatch([NotNull] RegexMatchExpression regexMatchExpression)
{
Check.NotNull(regexMatchExpression, nameof(regexMatchExpression));
var options = regexMatchExpression.Options;
Visit(regexMatchExpression.Match);
Sql.Append(" ~ ");
// PG regexps are singleline by default
if (options == RegexOptions.Singleline)
{
Visit(regexMatchExpression.Pattern);
return regexMatchExpression;
}
Sql.Append("('(?");
if (options.HasFlag(RegexOptions.IgnoreCase)) {
Sql.Append('i');
}
if (options.HasFlag(RegexOptions.Multiline)) {
Sql.Append('n');
}
else if (!options.HasFlag(RegexOptions.Singleline)) {
// In .NET's default mode, . doesn't match newlines but PostgreSQL it does.
Sql.Append('p');
}
if (options.HasFlag(RegexOptions.IgnorePatternWhitespace))
{
Sql.Append('x');
}
Sql.Append(")' || ");
Visit(regexMatchExpression.Pattern);
Sql.Append(')');
return regexMatchExpression;
}
public Expression VisitAtTimeZone([NotNull] AtTimeZoneExpression atTimeZoneExpression)
{
Check.NotNull(atTimeZoneExpression, nameof(atTimeZoneExpression));
Visit(atTimeZoneExpression.TimestampExpression);
Sql.Append(" AT TIME ZONE '");
Sql.Append(atTimeZoneExpression.TimeZone);
Sql.Append('\'');
return atTimeZoneExpression;
}
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using JetBrains.Annotations;
using Microsoft.Data.Entity.Query.Expressions;
using Microsoft.Data.Entity.Storage;
using Microsoft.Data.Entity.Utilities;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Query.Sql.Internal
{
public class NpgsqlQuerySqlGeneratorFactory : QuerySqlGeneratorFactoryBase
{
public NpgsqlQuerySqlGeneratorFactory(
[NotNull] IRelationalCommandBuilderFactory commandBuilderFactory,
[NotNull] ISqlGenerationHelper sqlGenerationHelper,
[NotNull] IParameterNameGeneratorFactory parameterNameGeneratorFactory,
[NotNull] IRelationalTypeMapper relationalTypeMapper)
: base(
Check.NotNull(commandBuilderFactory, nameof(commandBuilderFactory)),
Check.NotNull(sqlGenerationHelper, nameof(sqlGenerationHelper)),
Check.NotNull(parameterNameGeneratorFactory, nameof(parameterNameGeneratorFactory)),
Check.NotNull(relationalTypeMapper, nameof(relationalTypeMapper)))
{
}
public override IQuerySqlGenerator CreateDefault(SelectExpression selectExpression)
=> new NpgsqlQuerySqlGenerator(
CommandBuilderFactory,
SqlGenerationHelper,
ParameterNameGeneratorFactory,
RelationalTypeMapper,
Check.NotNull(selectExpression, nameof(selectExpression)));
}
}
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Data.Entity.Metadata;
using Microsoft.Data.Entity.Migrations.Operations;
using Microsoft.Data.Entity.Utilities;
using Microsoft.Data.Entity.Migrations;
using Npgsql;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Storage.Internal
{
public class NpgsqlDatabaseCreator : RelationalDatabaseCreator
{
private readonly NpgsqlRelationalConnection _connection;
private readonly IMigrationsSqlGenerator _migrationsSqlGenerator;
private readonly IRawSqlCommandBuilder _rawSqlCommandBuilder;
public NpgsqlDatabaseCreator(
[NotNull] NpgsqlRelationalConnection connection,
[NotNull] IMigrationsModelDiffer modelDiffer,
[NotNull] IMigrationsSqlGenerator migrationsSqlGenerator,
[NotNull] IModel model,
[NotNull] IRawSqlCommandBuilder rawSqlCommandBuilder)
: base(model, connection, modelDiffer, migrationsSqlGenerator)
{
Check.NotNull(rawSqlCommandBuilder, nameof(rawSqlCommandBuilder));
_connection = connection;
_migrationsSqlGenerator = migrationsSqlGenerator;
_rawSqlCommandBuilder = rawSqlCommandBuilder;
}
public override void Create()
{
using (var masterConnection = _connection.CreateMasterConnection())
{
CreateCreateOperations().ExecuteNonQuery(masterConnection);
ClearPool();
}
}
public override async Task CreateAsync(CancellationToken cancellationToken = default(CancellationToken))
{
using (var masterConnection = _connection.CreateMasterConnection())
{
await CreateCreateOperations().ExecuteNonQueryAsync(masterConnection, cancellationToken);
ClearPool();
}
}
protected override bool HasTables()
=> (bool)CreateHasTablesCommand().ExecuteScalar(_connection);
protected override async Task<bool> HasTablesAsync(CancellationToken cancellationToken = default(CancellationToken))
=> (bool)(await CreateHasTablesCommand().ExecuteScalarAsync(_connection, cancellationToken: cancellationToken));
private IRelationalCommand CreateHasTablesCommand()
=> _rawSqlCommandBuilder
.Build(@"
SELECT CASE WHEN COUNT(*) = 0 THEN FALSE ELSE TRUE END
FROM information_schema.tables
WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')
");
private IEnumerable<IRelationalCommand> CreateCreateOperations()
=> _migrationsSqlGenerator.Generate(new[] { new NpgsqlCreateDatabaseOperation { Name = _connection.DbConnection.Database } });
public override bool Exists()
{
try
{
_connection.Open();
_connection.Close();
return true;
}
catch (NpgsqlException e)
{
if (IsDoesNotExist(e))
{
return false;
}
throw;
}
}
public override async Task<bool> ExistsAsync(CancellationToken cancellationToken = default(CancellationToken))
{
try
{
await _connection.OpenAsync(cancellationToken);
_connection.Close();
return true;
}
catch (NpgsqlException e)
{
if (IsDoesNotExist(e))
{
return false;
}
throw;
}
}
// Login failed is thrown when database does not exist (See Issue #776)
private static bool IsDoesNotExist(NpgsqlException exception) => exception.Code == "3D000";
public override void Delete()
{
ClearAllPools();
using (var masterConnection = _connection.CreateMasterConnection())
{
CreateDropCommands().ExecuteNonQuery(masterConnection);
}
}
public override async Task DeleteAsync(CancellationToken cancellationToken = default(CancellationToken))
{
ClearAllPools();
using (var masterConnection = _connection.CreateMasterConnection())
{
await CreateDropCommands().ExecuteNonQueryAsync(masterConnection, cancellationToken);
}
}
private IEnumerable<IRelationalCommand> CreateDropCommands()
{
var operations = new MigrationOperation[]
{
// TODO Check DbConnection.Database always gives us what we want
// Issue #775
new NpgsqlDropDatabaseOperation { Name = _connection.DbConnection.Database }
};
var masterCommands = _migrationsSqlGenerator.Generate(operations);
return masterCommands;
}
// Clear connection pools in case there are active connections that are pooled
private static void ClearAllPools() => NpgsqlConnection.ClearAllPools();
// Clear connection pool for the database connection since after the 'create database' call, a previously
// invalid connection may now be valid.
private void ClearPool() => NpgsqlConnection.ClearPool((NpgsqlConnection)_connection.DbConnection);
}
}
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Reflection;
using JetBrains.Annotations;
using Microsoft.Data.Entity.Infrastructure;
using Microsoft.Data.Entity.Internal;
using Microsoft.Data.Entity.Metadata;
using Microsoft.Data.Entity.Metadata.Conventions.Internal;
using Microsoft.Data.Entity.Migrations;
using Microsoft.Data.Entity.Migrations.Internal;
using Microsoft.Data.Entity.Query;
using Microsoft.Data.Entity.Query.ExpressionTranslators;
using Microsoft.Data.Entity.Query.ExpressionTranslators.Internal;
using Microsoft.Data.Entity.Query.Internal;
using Microsoft.Data.Entity.Query.Sql;
using Microsoft.Data.Entity.Query.Sql.Internal;
using Microsoft.Data.Entity.Update;
using Microsoft.Data.Entity.Update.Internal;
using Microsoft.Data.Entity.ValueGeneration;
using Microsoft.Data.Entity.ValueGeneration.Internal;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Storage.Internal
{
public class NpgsqlDatabaseProviderServices : RelationalDatabaseProviderServices
{
public NpgsqlDatabaseProviderServices([NotNull] IServiceProvider services)
: base(services)
{
}
public override string InvariantName => GetType().GetTypeInfo().Assembly.GetName().Name;
public override IDatabaseCreator Creator => GetService<NpgsqlDatabaseCreator>();
public override IRelationalConnection RelationalConnection => GetService<NpgsqlRelationalConnection>();
public override ISqlGenerationHelper SqlGenerationHelper => GetService<NpgsqlSqlGenerationHelper>();
public override IRelationalDatabaseCreator RelationalDatabaseCreator => GetService<NpgsqlDatabaseCreator>();
public override IConventionSetBuilder ConventionSetBuilder => GetService<NpgsqlConventionSetBuilder>();
public override IMigrationsAnnotationProvider MigrationsAnnotationProvider => GetService<NpgsqlMigrationsAnnotationProvider>();
public override IHistoryRepository HistoryRepository => GetService<NpgsqlHistoryRepository>();
public override IMigrationsSqlGenerator MigrationsSqlGenerator => GetService<NpgsqlMigrationsSqlGenerator>();
public override IModelSource ModelSource => GetService<NpgsqlModelSource>();
public override IUpdateSqlGenerator UpdateSqlGenerator => GetService<NpgsqlUpdateSqlGenerator>();
public override IValueGeneratorCache ValueGeneratorCache => GetService<NpgsqlValueGeneratorCache>();
public override IRelationalTypeMapper TypeMapper => GetService<NpgsqlTypeMapper>();
public override IModificationCommandBatchFactory ModificationCommandBatchFactory => GetService<NpgsqlModificationCommandBatchFactory>();
public override IRelationalValueBufferFactoryFactory ValueBufferFactoryFactory => GetService<TypedRelationalValueBufferFactoryFactory>();
public override IRelationalAnnotationProvider AnnotationProvider => GetService<NpgsqlAnnotationProvider>();
public override IMethodCallTranslator CompositeMethodCallTranslator => GetService<NpgsqlCompositeMethodCallTranslator>();
public override IMemberTranslator CompositeMemberTranslator => GetService<NpgsqlCompositeMemberTranslator>();
public override IQueryCompilationContextFactory QueryCompilationContextFactory => GetService<NpgsqlQueryCompilationContextFactory>();
public override IQuerySqlGeneratorFactory QuerySqlGeneratorFactory => GetService<NpgsqlQuerySqlGeneratorFactory>();
}
}
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Data.Common;
using JetBrains.Annotations;
using Microsoft.Data.Entity.Infrastructure;
using Microsoft.Data.Entity.Utilities;
using Microsoft.Extensions.Logging;
using Npgsql;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Storage.Internal
{
public class NpgsqlRelationalConnection : RelationalConnection
{
public NpgsqlRelationalConnection(
[NotNull] IDbContextOptions options,
// ReSharper disable once SuggestBaseTypeForParameter
[NotNull] ILogger<NpgsqlConnection> logger)
: base(options, logger)
{
}
private NpgsqlRelationalConnection(
[NotNull] IDbContextOptions options, [NotNull] ILogger logger)
: base(options, logger)
{
}
// TODO: Consider using DbProviderFactory to create connection instance
// Issue #774
protected override DbConnection CreateDbConnection() => new NpgsqlConnection(ConnectionString);
public NpgsqlRelationalConnection CreateMasterConnection()
{
var csb = new NpgsqlConnectionStringBuilder(ConnectionString) {
Database = "postgres",
Pooling = false
};
var masterConn = ((NpgsqlConnection)DbConnection).CloneWith(csb.ToString());
var optionsBuilder = new DbContextOptionsBuilder();
optionsBuilder.UseNpgsql(masterConn);
return new NpgsqlRelationalConnection(optionsBuilder.Options, Logger);
}
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Globalization;
using System.Linq;
using System.Text;
using JetBrains.Annotations;
using Microsoft.Data.Entity.Utilities;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Storage.Internal
{
public class NpgsqlSqlGenerationHelper : RelationalSqlGenerationHelper
{
public override string EscapeIdentifier([NotNull] string identifier)
=> Check.NotEmpty(identifier, nameof(identifier)).Replace("\"", "\"\"");
public override string DelimitIdentifier([NotNull] string identifier)
=> $"\"{EscapeIdentifier(Check.NotEmpty(identifier, nameof(identifier)))}\"";
protected override string GenerateLiteralValue(byte[] literal)
{
Check.NotNull(literal, nameof(literal));
var builder = new StringBuilder(literal.Length * 2 + 6);
builder.Append("E'\\\\x");
foreach (var b in literal) {
builder.Append(b.ToString("X2", CultureInfo.InvariantCulture));
}
builder.Append('\'');
return builder.ToString();
}
protected override string GenerateLiteralValue(bool literal) => literal ? "TRUE" : "FALSE";
protected override string GenerateLiteralValue(DateTime literal) => "'" + literal.ToString(@"yyyy-MM-dd HH\:mm\:ss.fffffff") + "'";
protected override string GenerateLiteralValue(DateTimeOffset literal) => "'" + literal.ToString(@"yyyy-MM-dd HH\:mm\:ss.fffffffzzz") + "'";
}
}
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.Data.Entity.Metadata;
using Npgsql;
using Npgsql.TypeHandlers;
// ReSharper disable once CheckNamespace
namespace Microsoft.Data.Entity.Storage.Internal
{
// TODO: BIT(1) vs. BIT(N)
// TODO: Enums - https://github.com/aspnet/EntityFramework/issues/3620
// TODO: Arrays? But this would conflict with navigation...
public class NpgsqlTypeMapper : RelationalTypeMapper
{
readonly Dictionary<string, RelationalTypeMapping> _simpleNameMappings;
readonly Dictionary<Type, RelationalTypeMapping> _simpleMappings;
public NpgsqlTypeMapper()
{
// First, PostgreSQL type name (string) -> RelationalTypeMapping
_simpleNameMappings = TypeHandlerRegistry.HandlerTypes.Values
// Base types
.Where(tam => tam.Mapping.NpgsqlDbType.HasValue)
.Select(tam => new {
Name = tam.Mapping.PgName,
Mapping = (RelationalTypeMapping)new NpgsqlTypeMapping(tam.Mapping.PgName, GetTypeHandlerTypeArgument(tam.HandlerType), tam.Mapping.NpgsqlDbType.Value)
})
// Enums
//.Concat(TypeHandlerRegistry.GlobalEnumMappings.Select(kv => new {
// Name = kv.Key,
// Mapping = (RelationalTypeMapping)new NpgsqlTypeMapping(kv.Key, ((IEnumHandler)kv.Value).EnumType)
//}))
// Composites
.Concat(TypeHandlerRegistry.GlobalCompositeMappings.Select(kv => new {
Name = kv.Key,
Mapping = (RelationalTypeMapping)new NpgsqlTypeMapping(kv.Key, ((ICompositeHandler)kv.Value).CompositeType)
}))
// Output
.ToDictionary(x => x.Name, x => x.Mapping);
// Second, CLR type -> RelationalTypeMapping
_simpleMappings = TypeHandlerRegistry.HandlerTypes.Values
// Base types
.Select(tam => tam.Mapping)
.Where(m => m.NpgsqlDbType.HasValue)
.SelectMany(m => m.ClrTypes, (m, t) => new {
Type = t,
Mapping = (RelationalTypeMapping)new NpgsqlTypeMapping(m.PgName, t, m.NpgsqlDbType.Value)
})
// Enums
//.Concat(TypeHandlerRegistry.GlobalEnumMappings.Select(kv => new {
// Type = ((IEnumHandler)kv.Value).EnumType,
// Mapping = (RelationalTypeMapping)new NpgsqlTypeMapping(kv.Key, ((IEnumHandler)kv.Value).EnumType)
//}))
// Composites
.Concat(TypeHandlerRegistry.GlobalCompositeMappings.Select(kv => new {
Type = ((ICompositeHandler)kv.Value).CompositeType,
Mapping = (RelationalTypeMapping)new NpgsqlTypeMapping(kv.Key, ((ICompositeHandler)kv.Value).CompositeType)
}))
// Output
.ToDictionary(x => x.Type, x => x.Mapping);
}
protected override string GetColumnType(IProperty property) => property.Npgsql().ColumnType;
protected override IReadOnlyDictionary<Type, RelationalTypeMapping> GetSimpleMappings()
=> _simpleMappings;
protected override IReadOnlyDictionary<string, RelationalTypeMapping> GetSimpleNameMappings()
=> _simpleNameMappings;
static Type GetTypeHandlerTypeArgument(Type handler)
{
while (!handler.GetTypeInfo().IsGenericType || handler.GetGenericTypeDefinition() != typeof(TypeHandler<>))
{
handler = handler.GetTypeInfo().BaseType;
if (handler == null)
{
throw new Exception("Npgsql type handler doesn't inherit from TypeHandler<>?");
}
}
return handler.GetGenericArguments()[0];
}
}
}
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Data.Entity.Storage;
using Npgsql;
using NpgsqlTypes;
namespace Microsoft.Data.Entity.Storage.Internal
{
public class NpgsqlTypeMapping : RelationalTypeMapping
{
public new NpgsqlDbType? StoreType { get; }
internal NpgsqlTypeMapping([NotNull] string defaultTypeName, [NotNull] Type clrType, NpgsqlDbType storeType)
: base(defaultTypeName, clrType)
{
StoreType = storeType;
}
internal NpgsqlTypeMapping([NotNull] string defaultTypeName, [NotNull] Type clrType)
: base(defaultTypeName, clrType)
{ }
protected override void ConfigureParameter([NotNull] DbParameter parameter)
{
if (StoreType.HasValue)
{
((NpgsqlParameter) parameter).NpgsqlDbType = StoreType.Value;
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>
System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089
</value>
</resheader>
<resheader name="writer">
<value>
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089
</value>
</resheader>
<data name="InvalidEnumValue" xml:space="preserve">
<value>The value provided for argument '{argumentName}' must be a valid value of enum type '{enumType}'.</value>
</data>
<data name="SequenceBadBlockSize" xml:space="preserve">
<value>The increment value of '{increment}' for sequence '{sequenceName}' cannot be used for value generation. Sequences used for value generation must have positive increments.</value>
</data>
<data name="IdentityBadType" xml:space="preserve">
<value>Identity value generation cannot be used for the property '{property}' on entity type '{entityType}' because the property type is '{propertyType}'. Identity value generation can only be used with signed integer properties.</value>
</data>
<data name="SequenceBadType" xml:space="preserve">
<value>SQL Server sequences cannot be used to generate values for the property '{property}' on entity type '{entityType}' because the property type is '{propertyType}'. Sequences can only be used with integer properties.</value>
</data>
<data name="SqlServerNotInUse" xml:space="preserve">
<value>SQL Server-specific methods can only be used when the context is using a SQL Server data store.</value>
</data>
</root>
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Data.Entity.Storage;
using Microsoft.Data.Entity.Utilities;
using Npgsql;
namespace Microsoft.Data.Entity.Update.Internal
{
using RelationalStrings = Microsoft.Data.Entity.Internal.RelationalStrings;
/// <remarks>
/// The usual ModificationCommandBatch implementation is <see cref="AffectedCountModificationCommandBatch"/>,
/// which relies on <see cref="SqlGenerator.AppendSelectAffectedCountCommand"/> to fetch the number of
/// rows modified via SQL.
///
/// PostgreSQL actually has no way of selecting the modified row count.
/// SQL defines GET DIAGNOSTICS which should provide this, but in PostgreSQL it's only available
/// in PL/pgSQL. See http://www.postgresql.org/docs/9.4/static/unsupported-features-sql-standard.html,
/// identifier F121-01.
///
/// Instead, the affected row count can be accessed in the PostgreSQL protocol itself, which seems
/// cleaner and more efficient anyway (no additional query).
/// </remarks>
public class NpgsqlModificationCommandBatch : ReaderModificationCommandBatch
{
public NpgsqlModificationCommandBatch(
[NotNull] IRelationalCommandBuilderFactory commandBuilderFactory,
[NotNull] ISqlGenerationHelper sqlGenerationHelper,
[NotNull] IUpdateSqlGenerator updateSqlGenerator,
[NotNull] IRelationalValueBufferFactoryFactory valueBufferFactoryFactory)
: base(commandBuilderFactory, sqlGenerationHelper, updateSqlGenerator, valueBufferFactoryFactory)
{
}
protected override bool CanAddCommand(ModificationCommand modificationCommand)
=> ModificationCommands.Count < NpgsqlCommand.MaxStatements;
protected override bool IsCommandTextValid()
=> true;
protected override void Consume(DbDataReader reader)
{
var npgsqlReader = (NpgsqlDataReader)reader;
Debug.Assert(npgsqlReader.Statements.Count == ModificationCommands.Count, $"Reader has {npgsqlReader.Statements.Count} statements, expected {ModificationCommands.Count}");
var commandIndex = 0;
try
{
while (true)
{
// Find the next propagating command, if any
int nextPropagating;
for (nextPropagating = commandIndex;
nextPropagating < ModificationCommands.Count &&
!ModificationCommands[nextPropagating].RequiresResultPropagation;
nextPropagating++) ;
// Go over all non-propagating commands before the next propagating one,
// make sure they executed
for (; commandIndex < nextPropagating; commandIndex++)
{
if (npgsqlReader.Statements[commandIndex].Rows == 0)
{
throw new DbUpdateConcurrencyException(
RelationalStrings.UpdateConcurrencyException(1, 0),
ModificationCommands[commandIndex].Entries
);
}
}
if (nextPropagating == ModificationCommands.Count)
{
Debug.Assert(!reader.NextResult(), "Expected less resultsets");
break;
}
// Propagate to results from the reader to the ModificationCommand
var modificationCommand = ModificationCommands[commandIndex++];
if (!reader.Read())
{
throw new DbUpdateConcurrencyException(
RelationalStrings.UpdateConcurrencyException(1, 0),
modificationCommand.Entries);
}
var valueBufferFactory = CreateValueBufferFactory(modificationCommand.ColumnModifications);
modificationCommand.PropagateResults(valueBufferFactory.Create(reader));
reader.NextResult();
}
}
catch (DbUpdateException)
{
throw;
}
catch (Exception ex)
{
throw new DbUpdateException(
RelationalStrings.UpdateStoreException,
ex,
ModificationCommands[commandIndex].Entries);
}
}
protected override async Task ConsumeAsync(
DbDataReader reader,
CancellationToken cancellationToken = default(CancellationToken))
{
var npgsqlReader = (NpgsqlDataReader)reader;
Debug.Assert(npgsqlReader.Statements.Count == ModificationCommands.Count, $"Reader has {npgsqlReader.Statements.Count} statements, expected {ModificationCommands.Count}");
var commandIndex = 0;
try
{
while (true)
{
// Find the next propagating command, if any
int nextPropagating;
for (nextPropagating = commandIndex;
nextPropagating < ModificationCommands.Count &&
!ModificationCommands[nextPropagating].RequiresResultPropagation;
nextPropagating++)
;
// Go over all non-propagating commands before the next propagating one,
// make sure they executed
for (; commandIndex < nextPropagating; commandIndex++)
{
if (npgsqlReader.Statements[commandIndex].Rows == 0)
{
throw new DbUpdateConcurrencyException(
RelationalStrings.UpdateConcurrencyException(1, 0),
ModificationCommands[commandIndex].Entries
);
}
}
if (nextPropagating == ModificationCommands.Count)
{
Debug.Assert(!(await reader.NextResultAsync(cancellationToken)), "Expected less resultsets");
break;
}
// Extract result from the command and propagate it
var modificationCommand = ModificationCommands[commandIndex++];
if (!(await reader.ReadAsync(cancellationToken)))
{
throw new DbUpdateConcurrencyException(
RelationalStrings.UpdateConcurrencyException(1, 0),
modificationCommand.Entries
);
}
var valueBufferFactory = CreateValueBufferFactory(modificationCommand.ColumnModifications);
modificationCommand.PropagateResults(valueBufferFactory.Create(reader));
await reader.NextResultAsync(cancellationToken);
}
}
catch (DbUpdateException)
{
throw;
}
catch (Exception ex)
{
throw new DbUpdateException(
RelationalStrings.UpdateStoreException,
ex,
ModificationCommands[commandIndex].Entries);
}
}
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using JetBrains.Annotations;
using Microsoft.Data.Entity.Infrastructure;
using Microsoft.Data.Entity.Storage;
using Microsoft.Data.Entity.Utilities;
namespace Microsoft.Data.Entity.Update.Internal
{
public class NpgsqlModificationCommandBatchFactory : IModificationCommandBatchFactory
{
private readonly IRelationalCommandBuilderFactory _commandBuilderFactory;
private readonly ISqlGenerationHelper _sqlGenerationHelper;
private readonly NpgsqlUpdateSqlGenerator _updateSqlGenerator;
private readonly IRelationalValueBufferFactoryFactory _valueBufferFactoryFactory;
private readonly IDbContextOptions _options;
public NpgsqlModificationCommandBatchFactory(
[NotNull] IRelationalCommandBuilderFactory commandBuilderFactory,
[NotNull] ISqlGenerationHelper sqlGenerationHelper,
[NotNull] NpgsqlUpdateSqlGenerator updateSqlGenerator,
[NotNull] IRelationalValueBufferFactoryFactory valueBufferFactoryFactory,
[NotNull] IDbContextOptions options)
{
Check.NotNull(commandBuilderFactory, nameof(commandBuilderFactory));
Check.NotNull(sqlGenerationHelper, nameof(sqlGenerationHelper));
Check.NotNull(updateSqlGenerator, nameof(updateSqlGenerator));
Check.NotNull(valueBufferFactoryFactory, nameof(valueBufferFactoryFactory));
Check.NotNull(options, nameof(options));
_commandBuilderFactory = commandBuilderFactory;
_sqlGenerationHelper = sqlGenerationHelper;
_updateSqlGenerator = updateSqlGenerator;
_valueBufferFactoryFactory = valueBufferFactoryFactory;
_options = options;
}
public virtual ModificationCommandBatch Create()
{
return new NpgsqlModificationCommandBatch(
_commandBuilderFactory,
_sqlGenerationHelper,
_updateSqlGenerator,
_valueBufferFactoryFactory);
}
}
}
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using JetBrains.Annotations;
using Microsoft.Data.Entity.Storage;
using Microsoft.Data.Entity.Utilities;
namespace Microsoft.Data.Entity.Update.Internal
{
public class NpgsqlUpdateSqlGenerator : UpdateSqlGenerator
{
public NpgsqlUpdateSqlGenerator([NotNull] ISqlGenerationHelper sqlGenerationHelper)
: base(sqlGenerationHelper)
{
}
public override ResultSetMapping AppendInsertOperation(StringBuilder commandStringBuilder, ModificationCommand command, int commandPosition)
{
Check.NotNull(commandStringBuilder, nameof(commandStringBuilder));
Check.NotNull(command, nameof(command));
var operations = command.ColumnModifications;
var writeOperations = operations.Where(o => o.IsWrite).ToArray();
var readOperations = operations.Where(o => o.IsRead).ToArray();
AppendInsertCommandHeader(commandStringBuilder, command.TableName, command.Schema, writeOperations);
AppendValuesHeader(commandStringBuilder, writeOperations);
AppendValues(commandStringBuilder, writeOperations);
if (readOperations.Length > 0)
{
AppendReturningClause(commandStringBuilder, readOperations);
}
commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator).AppendLine();
return ResultSetMapping.NoResultSet;
}
public override ResultSetMapping AppendUpdateOperation(
StringBuilder commandStringBuilder,
ModificationCommand command,
int commandPosition)
{
Check.NotNull(commandStringBuilder, nameof(commandStringBuilder));
Check.NotNull(command, nameof(command));
var tableName = command.TableName;
var schemaName = command.Schema;
var operations = command.ColumnModifications;
var writeOperations = operations.Where(o => o.IsWrite).ToArray();
var conditionOperations = operations.Where(o => o.IsCondition).ToArray();
var readOperations = operations.Where(o => o.IsRead).ToArray();
AppendUpdateCommandHeader(commandStringBuilder, tableName, schemaName, writeOperations);
AppendWhereClause(commandStringBuilder, conditionOperations);
if (readOperations.Length > 0)
{
AppendReturningClause(commandStringBuilder, readOperations);
}
commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator).AppendLine();
return ResultSetMapping.NoResultSet;
}
// ReSharper disable once ParameterTypeCanBeEnumerable.Local
private void AppendReturningClause(
StringBuilder commandStringBuilder,
IReadOnlyList<ColumnModification> operations)
{
commandStringBuilder
.AppendLine()
.Append("RETURNING ")
.AppendJoin(operations.Select(c => SqlGenerationHelper.DelimitIdentifier(c.ColumnName)));
}
// This function is a temporary workaround for
// https://github.com/aspnet/EntityFramework/issues/3023
protected override void AppendWhereCondition(
[NotNull] StringBuilder commandStringBuilder,
[NotNull] ColumnModification columnModification,
bool useOriginalValue)
{
Check.NotNull(commandStringBuilder, nameof(commandStringBuilder));
Check.NotNull(columnModification, nameof(columnModification));
// In PostgreSQL, doing WHERE x = @p doesn't work if @p is null.
// IS NOT DISTINCT FROM does the same thing as equality but also returns true for null comparison.
// http://www.postgresql.org/docs/current/static/functions-comparison.html
commandStringBuilder
.Append(SqlGenerationHelper.DelimitIdentifier(columnModification.ColumnName))
.Append(" IS NOT DISTINCT FROM ")
.Append(
SqlGenerationHelper.GenerateParameterName(
useOriginalValue
? columnModification.OriginalParameterName
: columnModification.ParameterName));
}
public override void AppendBatchHeader(StringBuilder commandStringBuilder)
{
Check.NotNull(commandStringBuilder, nameof(commandStringBuilder));
// TODO: Npgsql
}
protected override void AppendIdentityWhereCondition(StringBuilder commandStringBuilder, ColumnModification columnModification)
{
throw new NotImplementedException();
}
protected override void AppendRowsAffectedWhereCondition(StringBuilder commandStringBuilder, int expectedRowsAffected)
{
throw new NotImplementedException();
}
public enum ResultsGrouping
{
OneResultSet,
OneCommandPerResultSet
}
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace System.Linq
{
[DebuggerStepThrough]
internal static class AsyncEnumerableExtensions
{
public static IAsyncEnumerable<TResult> Select<TSource, TResult>(
this IAsyncEnumerable<TSource> source,
Func<TSource, CancellationToken, Task<TResult>> selector)
=> new AsyncSelectEnumerable<TSource, TResult>(source, selector);
private class AsyncSelectEnumerable<TSource, TResult> : IAsyncEnumerable<TResult>
{
private readonly IAsyncEnumerable<TSource> _source;
private readonly Func<TSource, CancellationToken, Task<TResult>> _selector;
public AsyncSelectEnumerable(
IAsyncEnumerable<TSource> source,
Func<TSource, CancellationToken, Task<TResult>> selector)
{
_source = source;
_selector = selector;
}
public IAsyncEnumerator<TResult> GetEnumerator() => new AsyncSelectEnumerator(this);
private class AsyncSelectEnumerator : IAsyncEnumerator<TResult>
{
private readonly IAsyncEnumerator<TSource> _enumerator;
private readonly Func<TSource, CancellationToken, Task<TResult>> _selector;
public AsyncSelectEnumerator(AsyncSelectEnumerable<TSource, TResult> enumerable)
{
_enumerator = enumerable._source.GetEnumerator();
_selector = enumerable._selector;
}
public async Task<bool> MoveNext(CancellationToken cancellationToken)
{
if (!await _enumerator.MoveNext(cancellationToken))
{
return false;
}
Current = await _selector(_enumerator.Current, cancellationToken);
return true;
}
public TResult Current { get; private set; }
public void Dispose() => _enumerator.Dispose();
}
}
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using JetBrains.Annotations;
using Microsoft.Data.Entity.Internal;
namespace Microsoft.Data.Entity.Utilities
{
[DebuggerStepThrough]
internal static class Check
{
[ContractAnnotation("value:null => halt")]
public static T NotNull<T>([NoEnumeration] T value, [InvokerParameterName] [NotNull] string parameterName)
{
if (ReferenceEquals(value, null))
{
NotEmpty(parameterName, nameof(parameterName));
throw new ArgumentNullException(parameterName);
}
return value;
}
[ContractAnnotation("value:null => halt")]
public static T NotNull<T>(
[NoEnumeration] T value,
[InvokerParameterName] [NotNull] string parameterName,
[NotNull] string propertyName)
{
if (ReferenceEquals(value, null))
{
NotEmpty(parameterName, nameof(parameterName));
NotEmpty(propertyName, nameof(propertyName));
throw new ArgumentException(CoreStrings.ArgumentPropertyNull(propertyName, parameterName));
}
return value;
}
[ContractAnnotation("value:null => halt")]
public static IReadOnlyList<T> NotEmpty<T>(IReadOnlyList<T> value, [InvokerParameterName] [NotNull] string parameterName)
{
NotNull(value, parameterName);
if (value.Count == 0)
{
NotEmpty(parameterName, nameof(parameterName));
throw new ArgumentException(CoreStrings.CollectionArgumentIsEmpty(parameterName));
}
return value;
}
[ContractAnnotation("value:null => halt")]
public static string NotEmpty(string value, [InvokerParameterName] [NotNull] string parameterName)
{
Exception e = null;
if (ReferenceEquals(value, null))
{
e = new ArgumentNullException(parameterName);
}
else if (value.Trim().Length == 0)
{
e = new ArgumentException(CoreStrings.ArgumentIsEmpty(parameterName));
}
if (e != null)
{
NotEmpty(parameterName, nameof(parameterName));
throw e;
}
return value;
}
public static string NullButNotEmpty(string value, [InvokerParameterName] [NotNull] string parameterName)
{
if (!ReferenceEquals(value, null)
&& value.Length == 0)
{
NotEmpty(parameterName, nameof(parameterName));
throw new ArgumentException(CoreStrings.ArgumentIsEmpty(parameterName));
}
return value;
}
public static IReadOnlyList<T> HasNoNulls<T>(IReadOnlyList<T> value, [InvokerParameterName] [NotNull] string parameterName)
where T : class
{
NotNull(value, parameterName);
if (value.Any(e => e == null))
{
NotEmpty(parameterName, nameof(parameterName));
throw new ArgumentException(parameterName);
}
return value;
}
public static T IsDefined<T>(T value, [InvokerParameterName] [NotNull] string parameterName)
where T : struct
{
if (!Enum.IsDefined(typeof(T), value))
{
NotEmpty(parameterName, nameof(parameterName));
throw new ArgumentException(CoreStrings.InvalidEnumValue(parameterName, typeof(T)));
}
return value;
}
public static Type ValidEntityType(Type value, [InvokerParameterName] [NotNull] string parameterName)
{
if (!value.GetTypeInfo().IsClass)
{
NotEmpty(parameterName, nameof(parameterName));
throw new ArgumentException(CoreStrings.InvalidEntityType(parameterName, value));
}
return value;
}
}
}
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Diagnostics;
using System.Linq;
// ReSharper disable once CheckNamespace
namespace System.Collections.Generic
{
[DebuggerStepThrough]
internal static class EnumerableExtensions
{
public static string Join(this IEnumerable<object> source, string separator = ", ")
{
return string.Join(separator, source);
}
public static IEnumerable<T> Distinct<T>(
this IEnumerable<T> source, Func<T, T, bool> comparer)
where T : class
{
return source.Distinct(new DynamicEqualityComparer<T>(comparer));
}
private sealed class DynamicEqualityComparer<T> : IEqualityComparer<T>
where T : class
{
private readonly Func<T, T, bool> _func;
public DynamicEqualityComparer(Func<T, T, bool> func)
{
_func = func;
}
public bool Equals(T x, T y)
{
return _func(x, y);
}
public int GetHashCode(T obj)
{
return 0; // force Equals
}
}
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Diagnostics;
using System.Linq;
using System.Reflection;
// ReSharper disable once CheckNamespace
namespace System
{
[DebuggerStepThrough]
internal static class SharedTypeExtensions
{
public static Type UnwrapNullableType(this Type type) => Nullable.GetUnderlyingType(type) ?? type;
public static bool IsNullableType(this Type type)
{
var typeInfo = type.GetTypeInfo();
return !typeInfo.IsValueType
|| (typeInfo.IsGenericType
&& typeInfo.GetGenericTypeDefinition() == typeof(Nullable<>));
}
public static Type MakeNullable(this Type type)
=> type.IsNullableType()
? type
: typeof(Nullable<>).MakeGenericType(type);
public static bool IsInteger(this Type type)
{
type = type.UnwrapNullableType();
return type == typeof(int)
|| type == typeof(long)
|| type == typeof(short)
|| type == typeof(byte)
|| type == typeof(uint)
|| type == typeof(ulong)
|| type == typeof(ushort)
|| type == typeof(sbyte);
}
public static bool IsIntegerForSerial(this Type type)
{
type = type.UnwrapNullableType();
return type == typeof(int)
|| type == typeof(long)
|| type == typeof(short);
}
public static PropertyInfo GetAnyProperty(this Type type, string name)
{
var props = type.GetRuntimeProperties().Where(p => p.Name == name).ToList();
if (props.Count() > 1)
{
throw new AmbiguousMatchException();
}
return props.SingleOrDefault();
}
private static bool IsNonIntegerPrimitive(this Type type)
{
type = type.UnwrapNullableType();
return type == typeof(bool)
|| type == typeof(byte[])
|| type == typeof(char)
|| type == typeof(DateTime)
|| type == typeof(DateTimeOffset)
|| type == typeof(decimal)
|| type == typeof(double)
|| type == typeof(float)
|| type == typeof(Guid)
|| type == typeof(string)
|| type == typeof(TimeSpan)
|| type.GetTypeInfo().IsEnum;
}
public static bool IsPrimitive(this Type type)
=> type.IsInteger()
|| type.IsNonIntegerPrimitive();
public static Type UnwrapEnumType(this Type type)
=> type.GetTypeInfo().IsEnum ? Enum.GetUnderlyingType(type) : type;
}
}
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
namespace System.Text
{
internal static class StringBuilderExtensions
{
public static StringBuilder AppendJoin(
this StringBuilder stringBuilder, IEnumerable<string> values, string separator = ", ")
=> stringBuilder.AppendJoin(values, (sb, value) => sb.Append(value), separator);
public static StringBuilder AppendJoin<T>(
this StringBuilder stringBuilder, IEnumerable<T> values, Action<StringBuilder, T> joinAction,
string separator)
{
var appended = false;
foreach (var value in values)
{
joinAction(stringBuilder, value);
stringBuilder.Append(separator);
appended = true;
}
if (appended)
{
stringBuilder.Length -= separator.Length;
}
return stringBuilder;
}
}
}
namespace Microsoft.Data.Entity.ValueGeneration.Internal
{
public class NpgsqlValueGeneratorCache : ValueGeneratorCache
{
}
}
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-1.1.37.0" newVersion="1.1.37.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/></startup></configuration>
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="EntityFramework.Core" version="7.0.0-rc2-16583" targetFramework="net452" />
<package id="EntityFramework.Relational" version="7.0.0-rc2-16583" targetFramework="net452" />
<package id="Ix-Async" version="1.2.5" targetFramework="net452" />
<package id="Microsoft.Extensions.Caching.Abstractions" version="1.0.0-rc2-15948" targetFramework="net452" />
<package id="Microsoft.Extensions.Caching.Memory" version="1.0.0-rc2-15948" targetFramework="net452" />
<package id="Microsoft.Extensions.Configuration" version="1.0.0-rc1-final" targetFramework="net452" />
<package id="Microsoft.Extensions.Configuration.Abstractions" version="1.0.0-rc1-final" targetFramework="net452" />
<package id="Microsoft.Extensions.Configuration.Binder" version="1.0.0-rc1-final" targetFramework="net452" />
<package id="Microsoft.Extensions.DependencyInjection" version="1.0.0-rc2-15888" targetFramework="net452" />
<package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="1.0.0-rc2-15888" targetFramework="net452" />
<package id="Microsoft.Extensions.Logging" version="1.0.0-rc2-15926" targetFramework="net452" />
<package id="Microsoft.Extensions.Logging.Abstractions" version="1.0.0-rc2-15926" targetFramework="net452" />
<package id="Microsoft.Extensions.OptionsModel" version="1.0.0-rc2-15904" targetFramework="net452" />
<package id="Microsoft.Extensions.Primitives" version="1.0.0-rc2-15937" targetFramework="net452" />
<package id="Remotion.Linq" version="2.0.1" targetFramework="net452" />
<package id="System.Collections.Immutable" version="1.1.36" targetFramework="net452" />
<package id="System.Diagnostics.DiagnosticSource" version="4.0.0-rc2-23616" targetFramework="net452" />
<package id="System.Diagnostics.Tracing" version="4.0.0" targetFramework="net452" />
<package id="System.Runtime" version="4.0.0" targetFramework="net452" />
<package id="System.Threading" version="4.0.0" targetFramework="net452" />
</packages>
\ No newline at end of file
{
"version": "1.0.0-*",
"authors": [
"Shay Rojansky"
],
"description" : "PostgreSQL provider for Entity Framework 7",
"iconUrl": "http://www.npgsql.org/img/postgresql.gif",
"repository": {
"type": "git",
"url": "git://github.com/npgsql/npgsql"
},
"compile": "../Shared/*.cs",
"compilationOptions": {
"keyFile": "../../Npgsql.snk"
},
"dependencies" : {
"EntityFramework.Core": "7.0.0-rc2-*",
"EntityFramework.Relational": "7.0.0-rc2-*",
"Microsoft.Extensions.DependencyInjection.Abstractions": "1.0.0-rc2-*",
"Microsoft.Extensions.DependencyInjection": "1.0.0-rc2-*",
"Npgsql": "3.1.0-*"
},
"frameworks": {
"net451": {
"frameworkAssemblies": {
"System.Collections": { "version": "4.0.0.0", "type": "build" },
"System.Reflection": { "version": "4.0.0.0", "type": "build" },
"System.Diagnostics.Contracts": { "version": "4.0.0.0", "type": "build" },
"System.Linq.Expressions": { "version": "4.0.0.0", "type": "build" },
"System.Runtime": { "version": "4.0.0.0", "type": "build" }
}
},
"netstandard13": {
"dependencies": {
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0.24720" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.24720</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>5336f099-dff4-4439-9022-169aeb1fa737</ProjectGuid>
<RootNamespace>EntityFramework7.Npgsql.Design.FunctionalTests</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>
\ No newline at end of file
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("EntityFramework7.Npgsql.Design.FunctionalTests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("EntityFramework7.Npgsql.Design.FunctionalTests")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("1410d291-c519-4e74-ae3d-6bc6c4a7c1dc")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
using System;
using System.Collections.Generic;
namespace E2ETest.Namespace
{
public partial class AllDataTypes
{
public int AllDataTypesID { get; set; }
public long bigintColumn { get; set; }
public bool boolColumn { get; set; }
public byte[] byteaColumn { get; set; }
public string charColumn { get; set; }
public DateTime dateColumn { get; set; }
public decimal decimalColumn { get; set; }
public double doubleColumn { get; set; }
public int intColumn { get; set; }
public decimal moneyColumn { get; set; }
public decimal numericColumn { get; set; }
public float? realColumn { get; set; }
public short smallintColumn { get; set; }
public string textColumn { get; set; }
public TimeSpan? timeColumn { get; set; }
public DateTime? timestampColumn { get; set; }
public DateTime? timestampTzColumn { get; set; }
public Guid? uuidColumn { get; set; }
public string varcharColumn { get; set; }
}
}
using System;
using System.Collections.Generic;
namespace E2ETest.Namespace
{
public partial class OneToManyDependent
{
public int OneToManyDependentID1 { get; set; }
public int OneToManyDependentID2 { get; set; }
public int? OneToManyDependentFK1 { get; set; }
public int? OneToManyDependentFK2 { get; set; }
public string SomeDependentEndColumn { get; set; }
public virtual OneToManyPrincipal OneToManyDependentFK { get; set; }
}
}
using System;
using System.Collections.Generic;
namespace E2ETest.Namespace
{
public partial class OneToManyPrincipal
{
public OneToManyPrincipal()
{
OneToManyDependent = new HashSet<OneToManyDependent>();
}
public int OneToManyPrincipalID1 { get; set; }
public int OneToManyPrincipalID2 { get; set; }
public string Other { get; set; }
public virtual ICollection<OneToManyDependent> OneToManyDependent { get; set; }
}
}
using System;
using System.Collections.Generic;
namespace E2ETest.Namespace
{
public partial class OneToOneDependent
{
public int OneToOneDependentID1 { get; set; }
public int OneToOneDependentID2 { get; set; }
public string SomeDependentEndColumn { get; set; }
public virtual OneToOnePrincipal OneToOneDependentNavigation { get; set; }
}
}
using System;
using System.Collections.Generic;
namespace E2ETest.Namespace
{
public partial class OneToOneFKToUniqueKeyDependent
{
public int OneToOneFKToUniqueKeyDependentID1 { get; set; }
public int OneToOneFKToUniqueKeyDependentID2 { get; set; }
public int? OneToOneFKToUniqueKeyDependentFK1 { get; set; }
public int? OneToOneFKToUniqueKeyDependentFK2 { get; set; }
public string SomeColumn { get; set; }
public virtual OneToOneFKToUniqueKeyPrincipal OneToOneFKToUniqueKeyDependentFK { get; set; }
}
}
using System;
using System.Collections.Generic;
namespace E2ETest.Namespace
{
public partial class OneToOneFKToUniqueKeyPrincipal
{
public int OneToOneFKToUniqueKeyPrincipalID1 { get; set; }
public int OneToOneFKToUniqueKeyPrincipalID2 { get; set; }
public int OneToOneFKToUniqueKeyPrincipalUniqueKey1 { get; set; }
public int OneToOneFKToUniqueKeyPrincipalUniqueKey2 { get; set; }
public string SomePrincipalColumn { get; set; }
public virtual OneToOneFKToUniqueKeyDependent OneToOneFKToUniqueKeyDependent { get; set; }
}
}
using System;
using System.Collections.Generic;
namespace E2ETest.Namespace
{
public partial class OneToOnePrincipal
{
public int OneToOnePrincipalID1 { get; set; }
public int OneToOnePrincipalID2 { get; set; }
public string SomeOneToOnePrincipalColumn { get; set; }
public virtual OneToOneDependent OneToOneDependent { get; set; }
}
}
using System;
using System.Collections.Generic;
namespace E2ETest.Namespace
{
public partial class OneToOneSeparateFKDependent
{
public int OneToOneSeparateFKDependentID1 { get; set; }
public int OneToOneSeparateFKDependentID2 { get; set; }
public int? OneToOneSeparateFKDependentFK1 { get; set; }
public int? OneToOneSeparateFKDependentFK2 { get; set; }
public string SomeDependentEndColumn { get; set; }
public virtual OneToOneSeparateFKPrincipal OneToOneSeparateFKDependentFK { get; set; }
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册