Adds Oracle sample provider to EFCore.sln.

- Adds README.md for the sample.
This commit is contained in:
Andrew Peters 2017-09-07 11:32:36 -07:00
Родитель 38ba45f925
Коммит d5ab432da3
4 изменённых файлов: 57 добавлений и 181 удалений

Просмотреть файл

@ -61,6 +61,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFCore.Benchmarks", "benchm
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFCore.Benchmarks.EFCore", "test\EFCore.Benchmarks.EFCore\EFCore.Benchmarks.EFCore.csproj", "{8B289879-9CF1-4EFD-AD4B-781AEA94BDBE}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{C41FD56B-38CD-40E3-89E6-071A6C58E36C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "OracleProvider", "OracleProvider", "{EA847C1D-EC25-442B-A940-460969577CD5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OracleProvider", "samples\OracleProvider\src\OracleProvider\OracleProvider.csproj", "{9511216F-EC10-480D-AA8D-F72312C96962}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -175,6 +181,10 @@ Global
{8B289879-9CF1-4EFD-AD4B-781AEA94BDBE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8B289879-9CF1-4EFD-AD4B-781AEA94BDBE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8B289879-9CF1-4EFD-AD4B-781AEA94BDBE}.Release|Any CPU.Build.0 = Release|Any CPU
{9511216F-EC10-480D-AA8D-F72312C96962}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9511216F-EC10-480D-AA8D-F72312C96962}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9511216F-EC10-480D-AA8D-F72312C96962}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9511216F-EC10-480D-AA8D-F72312C96962}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -207,6 +217,8 @@ Global
{935B51B9-A9B9-4DA2-93A2-663D3BCEAA83} = {258D5057-81B9-40EC-A872-D21E27452749}
{E4F44442-7AD2-480D-AD6B-AAC4424F5FA7} = {258D5057-81B9-40EC-A872-D21E27452749}
{8B289879-9CF1-4EFD-AD4B-781AEA94BDBE} = {258D5057-81B9-40EC-A872-D21E27452749}
{EA847C1D-EC25-442B-A940-460969577CD5} = {C41FD56B-38CD-40E3-89E6-071A6C58E36C}
{9511216F-EC10-480D-AA8D-F72312C96962} = {EA847C1D-EC25-442B-A940-460969577CD5}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {285A5EB4-BCF4-40EB-B9E1-DF6DBCB5E705}

Просмотреть файл

@ -0,0 +1,44 @@
# Sample - Oracle Provider
**NB: This Oracle provider is a sample and is not production quality.**
## Limitations of the sample Oracle provider:
- Only works on full .NET - utilizes official Oracle managed ADO provider.
- Does not fully support Migrations. Only enough has been implemented to enable the runtime functional tests.
- Scaffolding is not supported.
- Update batching is not supported.
- OracleTransientExceptionDetector needs to be updated (impl. copied from SqlServer provider).
- OracleTypeMapper is implemented but likely needs more tuning.
- No Oracle specific features are "lit up".
## What works:
- All query tests passing (aside from a few failing due to various Oracle specific issues).
- All runtime tests passing (aside from those directly related to the limitations above).
## Running the tests
1) Install [Oracle Database 12c Release 2 (12.2.0.1.0) - Standard Edition 2](http://www.oracle.com/technetwork/database/enterprise-edition/downloads/index.html)
- When installing, ensure to enable pluggable databases - the sample relies on a specific pluggable database.
2) Use a shell to connect via SQLPlus:
```
> sqlplus / as sysdba
```
3) Create a pluggable database used to host the EF test databases:
```
CREATE PLUGGABLE DATABASE ef
ADMIN USER ef_pdb_admin IDENTIFIED BY ef_pdb_admin
ROLES = (DBA)
FILE_NAME_CONVERT = ('\pdbseed\', '\pdb_ef\');
```
4) Open the pluggable database:
```
ALTER PLUGGABLE DATABASE ef OPEN;
```

Просмотреть файл

@ -9,6 +9,7 @@
<TargetFrameworks>net461</TargetFrameworks>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<CodeAnalysisRuleSet>..\..\..\..\src\EFCore.ruleset</CodeAnalysisRuleSet>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
@ -24,11 +25,6 @@
<None Remove="Scaffolding\**" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Update\Internal\OracleModificationCommandBatch.cs" />
<Compile Remove="Update\Internal\SqlServerModificationCommandBatch.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\src\EFCore.Relational\EFCore.Relational.csproj" />
</ItemGroup>
@ -40,10 +36,6 @@
</ItemGroup>
<ItemGroup>
<None Update="App.config">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>App.cs</LastGenOutput>
</None>
<None Update="Properties\OracleStrings.Designer.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>OracleStrings.Designer.cs</LastGenOutput>

Просмотреть файл

@ -1,172 +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.Linq;
using System.Text;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Storage;
namespace Microsoft.EntityFrameworkCore.Update.Internal
{
public class SqlServerModificationCommandBatch : AffectedCountModificationCommandBatch
{
private const int DefaultNetworkPacketSizeBytes = 4096;
private const int MaxScriptLength = 65536 * DefaultNetworkPacketSizeBytes / 2;
private const int MaxParameterCount = 2100;
private const int MaxRowCount = 1000;
private int _parameterCount = 1; // Implicit parameter for the command text
private readonly int _maxBatchSize;
private readonly List<ModificationCommand> _bulkInsertCommands = new List<ModificationCommand>();
private int _commandsLeftToLengthCheck = 50;
public SqlServerModificationCommandBatch(
[NotNull] IRelationalCommandBuilderFactory commandBuilderFactory,
[NotNull] ISqlGenerationHelper sqlGenerationHelper,
// ReSharper disable once SuggestBaseTypeForParameter
[NotNull] ISqlServerUpdateSqlGenerator updateSqlGenerator,
[NotNull] IRelationalValueBufferFactoryFactory valueBufferFactoryFactory,
[CanBeNull] int? maxBatchSize)
: base(
commandBuilderFactory,
sqlGenerationHelper,
updateSqlGenerator,
valueBufferFactoryFactory)
{
if (maxBatchSize.HasValue
&& maxBatchSize.Value <= 0)
{
throw new ArgumentOutOfRangeException(nameof(maxBatchSize), RelationalStrings.InvalidMaxBatchSize);
}
_maxBatchSize = Math.Min(maxBatchSize ?? int.MaxValue, MaxRowCount);
}
protected new virtual ISqlServerUpdateSqlGenerator UpdateSqlGenerator => (ISqlServerUpdateSqlGenerator)base.UpdateSqlGenerator;
protected override bool CanAddCommand(ModificationCommand modificationCommand)
{
if (ModificationCommands.Count >= _maxBatchSize)
{
return false;
}
var additionalParameterCount = CountParameters(modificationCommand);
if (_parameterCount + additionalParameterCount >= MaxParameterCount)
{
return false;
}
_parameterCount += additionalParameterCount;
return true;
}
protected override bool IsCommandTextValid()
{
if (--_commandsLeftToLengthCheck < 0)
{
var commandTextLength = GetCommandText().Length;
if (commandTextLength >= MaxScriptLength)
{
return false;
}
var avarageCommandLength = commandTextLength / ModificationCommands.Count;
var expectedAdditionalCommandCapacity = (MaxScriptLength - commandTextLength) / avarageCommandLength;
_commandsLeftToLengthCheck = Math.Max(1, expectedAdditionalCommandCapacity / 4);
}
return true;
}
protected override int GetParameterCount()
=> _parameterCount;
private static int CountParameters(ModificationCommand modificationCommand)
{
var parameterCount = 0;
foreach (var columnModification in modificationCommand.ColumnModifications)
{
if (columnModification.UseCurrentValueParameter)
{
parameterCount++;
}
if (columnModification.UseOriginalValueParameter)
{
parameterCount++;
}
}
return parameterCount;
}
protected override void ResetCommandText()
{
base.ResetCommandText();
_bulkInsertCommands.Clear();
}
protected override string GetCommandText()
=> base.GetCommandText() + GetBulkInsertCommandText(ModificationCommands.Count);
private string GetBulkInsertCommandText(int lastIndex)
{
if (_bulkInsertCommands.Count == 0)
{
return string.Empty;
}
var stringBuilder = new StringBuilder();
var resultSetMapping = UpdateSqlGenerator.AppendBulkInsertOperation(stringBuilder, _bulkInsertCommands, lastIndex - _bulkInsertCommands.Count);
for (var i = lastIndex - _bulkInsertCommands.Count; i < lastIndex; i++)
{
CommandResultSet[i] = resultSetMapping;
}
if (resultSetMapping != ResultSetMapping.NoResultSet)
{
CommandResultSet[lastIndex - 1] = ResultSetMapping.LastInResultSet;
}
return stringBuilder.ToString();
}
protected override void UpdateCachedCommandText(int commandPosition)
{
var newModificationCommand = ModificationCommands[commandPosition];
if (newModificationCommand.EntityState == EntityState.Added)
{
if (_bulkInsertCommands.Count > 0
&& !CanBeInsertedInSameStatement(_bulkInsertCommands[0], newModificationCommand))
{
CachedCommandText.Append(GetBulkInsertCommandText(commandPosition));
_bulkInsertCommands.Clear();
}
_bulkInsertCommands.Add(newModificationCommand);
LastCachedCommandIndex = commandPosition;
}
else
{
CachedCommandText.Append(GetBulkInsertCommandText(commandPosition));
_bulkInsertCommands.Clear();
base.UpdateCachedCommandText(commandPosition);
}
}
private static bool CanBeInsertedInSameStatement(ModificationCommand firstCommand, ModificationCommand secondCommand)
=> string.Equals(firstCommand.TableName, secondCommand.TableName, StringComparison.Ordinal)
&& string.Equals(firstCommand.Schema, secondCommand.Schema, StringComparison.Ordinal)
&& firstCommand.ColumnModifications.Where(o => o.IsWrite).Select(o => o.ColumnName).SequenceEqual(
secondCommand.ColumnModifications.Where(o => o.IsWrite).Select(o => o.ColumnName))
&& firstCommand.ColumnModifications.Where(o => o.IsRead).Select(o => o.ColumnName).SequenceEqual(
secondCommand.ColumnModifications.Where(o => o.IsRead).Select(o => o.ColumnName));
}
}