Skip to content

Commit

Permalink
.27
Browse files Browse the repository at this point in the history
  • Loading branch information
drunkcod committed Feb 23, 2017
1 parent e590dfc commit 3fb90f2
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 65 deletions.
8 changes: 4 additions & 4 deletions DataBoss.Program/DataBoss.Program.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<ProjectGuid>{8E941F8D-9745-44C9-AC73-DF5E079D8E8E}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>DataBoss</RootNamespace>
<AssemblyName>DataBoss</AssemblyName>
<AssemblyName>DataBoss.Program</AssemblyName>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
Expand All @@ -35,9 +35,6 @@
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\DataBoss\Properties\AssemblyInfo.cs">
<Link>Properties\AssemblyInfo.cs</Link>
</Compile>
<Compile Include="..\DataBoss\Properties\Version.cs">
<Link>Properties\Version.cs</Link>
</Compile>
Expand All @@ -50,4 +47,7 @@
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="AfterBuild">
<Move SourceFiles="$(OutputPath)$(AssemblyName).exe" DestinationFiles="$(OutputPath)DataBoss.exe" />
</Target>
</Project>
2 changes: 1 addition & 1 deletion DataBoss.Program/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

namespace DataBoss
{

delegate int DataBossAction(DataBoss program);

class Program
Expand All @@ -17,7 +18,6 @@ static int Main(string[] args) {
Console.WriteLine(GetUsageString());
return 0;
}

var log = new DataBossConsoleLog();
try {
var cc = DataBossConfiguration.ParseCommandConfig(args);
Expand Down
4 changes: 4 additions & 0 deletions DataBoss.Specs/DataBossDbTypeSpec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ public void columnsize(string dataType, int columnSize, string expected) =>
[DisplayAs("{0} maps to db type {1}")
,Row(typeof(DateTime?), "datetime", true)
,Row(typeof(DateTime), "datetime", false)
,Row(typeof(byte?), "tinyint", true)
,Row(typeof(byte), "tinyint", false)
,Row(typeof(short?), "smallint", true)
,Row(typeof(short), "smallint", false)
,Row(typeof(int?), "int", true)
,Row(typeof(int), "int", false)
,Row(typeof(long?), "bigint", true)
Expand Down
1 change: 1 addition & 0 deletions DataBoss/DataBoss.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="DataBoss.cs" />
<Compile Include="DataBossBulkCopy.cs" />
<Compile Include="DataBossCommandAttribute.cs" />
<Compile Include="DataBossDbType.cs" />
<Compile Include="Data\NullAttributeProvider.cs" />
Expand Down
81 changes: 81 additions & 0 deletions DataBoss/DataBossBulkCopy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using DataBoss.Data;

namespace DataBoss
{
public class DataBossBulkCopy
{
const string TempTableName = "#$";

public readonly SqlConnection Connection;
public readonly SqlTransaction Transaction;
public int? CommandTimeout;

public DataBossBulkCopy(SqlConnection connection) : this(connection, null) { }

public DataBossBulkCopy(SqlConnection connection, SqlTransaction transaction) {
this.Connection = connection;
this.Transaction = transaction;
}

public void Insert(string destinationTable, IDataReader toInsert) {
using (var bulkCopy = NewBulkCopy(destinationTable)) {
for (var i = 0; i != toInsert.FieldCount; ++i) {
var n = toInsert.GetName(i);
bulkCopy.ColumnMappings.Add(n, n);
}
bulkCopy.WriteToServer(toInsert);
}
}

public void Insert<T>(string destinationTable, IEnumerable<T> rows) => Insert(destinationTable, SequenceDataReader.Create(rows, x => x.MapAll()));

public ICollection<int> InsertAndGetIdentities<T>(string destinationTable, IEnumerable<T> rows) {
var n = 0;
var toInsert = SequenceDataReader.Create(rows, x => {
x.Map("$", _ => ++n);
x.MapAll();
});

var scripter = new DataBossScripter();
Connection.ExecuteNonQuery(Transaction, $@"
{scripter.ScriptTable(TempTableName, toInsert)}
create clustered index [#$_$] on {TempTableName}([{toInsert.GetName(0)}])
");

using (var bulkCopy = NewBulkCopy(TempTableName))
bulkCopy.WriteToServer(toInsert);

var columns = string.Join(",", Enumerable.Range(1, toInsert.FieldCount - 1).Select(toInsert.GetName));
using (var cmd = Connection.CreateCommand($@"
insert {destinationTable} with(tablock)({columns})
output inserted.$identity as {nameof(IdRow.Id)}
select {columns}
from {TempTableName}
order by [$]
drop table {TempTableName}
"))
{
if(CommandTimeout.HasValue)
cmd.CommandTimeout = CommandTimeout.Value;
cmd.Transaction = Transaction;
using (var reader = ObjectReader.For(cmd.ExecuteReader(CommandBehavior.SingleResult | CommandBehavior.SequentialAccess))) {
var ids = reader.Read<IdRow>().Select(x => x.Id).ToList();
ids.Sort();
return ids;
}
}
}

SqlBulkCopy NewBulkCopy(string destinationTable) {
var bulkCopy = new SqlBulkCopy(Connection, SqlBulkCopyOptions.TableLock, Transaction) { DestinationTableName = destinationTable };
if(CommandTimeout.HasValue)
bulkCopy.BulkCopyTimeout = CommandTimeout.Value;
return bulkCopy;
}
}
}
8 changes: 4 additions & 4 deletions DataBoss/DataBossDbType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ static DataBossDbType MapType(Type type, ICustomAttributeProvider attributes, bo
return new DataBossDbType(column.TypeName, null, canBeNull);

switch (type.FullName) {
case "System.Byte": return new DataBossDbType("tinyint", 1, canBeNull);
case "System.Int16": return new DataBossDbType("smallint", 2, canBeNull);
case "System.Int32": return new DataBossDbType("int", 4, canBeNull);
case "System.Int64": return new DataBossDbType("bigint", 8, canBeNull);
case "System.Single": return new DataBossDbType("real", 4, canBeNull);
Expand All @@ -59,10 +61,8 @@ static DataBossDbType MapType(Type type, ICustomAttributeProvider attributes, bo

public override bool Equals(object obj) => (obj is DataBossDbType && this == (DataBossDbType)obj) || obj.Equals(this);

string FormatType() {
if(IsWideType(TypeName)) return FormatWideType();
return TypeName;
}
string FormatType() =>
IsWideType(TypeName) ? FormatWideType() : TypeName;

string FormatWideType() =>
(!ColumnSize.HasValue || ColumnSize.Value == 1) ? TypeName : $"{TypeName}({FormatWidth(ColumnSize.Value)})";
Expand Down
2 changes: 1 addition & 1 deletion DataBoss/Properties/Version.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
using System.Reflection;

[assembly: AssemblyVersion("0.0.0.26")]
[assembly: AssemblyVersion("0.0.0.27")]
60 changes: 6 additions & 54 deletions DataBoss/SqlConnectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,15 @@
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using DataBoss.Data;
using DataBoss.Diagnostics;

namespace DataBoss
{
struct IdRow { public int Id; }

public static class SqlConnectionExtensions
{
const string TempTableName = "#$";

public static SqlCommand CreateCommand(this SqlConnection connection, string cmdText) =>
new SqlCommand(cmdText, connection);

Expand Down Expand Up @@ -54,65 +51,20 @@ public static void Insert<T>(this SqlConnection connection, string destinationTa
Insert(connection, null, destinationTable, rows);

public static void Insert<T>(this SqlConnection connection, SqlTransaction transaction, string destinationTable, IEnumerable<T> rows) {
var toInsert = SequenceDataReader.Create(rows, x => x.MapAll());

using (var bulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.TableLock, transaction) { DestinationTableName = destinationTable }) {
for(var i = 0; i != toInsert.FieldCount; ++i) {
var n = toInsert.GetName(i);
bulkCopy.ColumnMappings.Add(n, n);
}
bulkCopy.WriteToServer(toInsert);
}
new DataBossBulkCopy(connection, transaction).Insert(destinationTable, rows);
}

public static void Insert(this SqlConnection connection, string destinationTable, IDataReader toInsert) =>
Insert(connection, null, destinationTable, toInsert);

public static void Insert(this SqlConnection connection, SqlTransaction transaction, string destinationTable, IDataReader toInsert) {
using (var bulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.TableLock, transaction) { DestinationTableName = destinationTable }) {
for (var i = 0; i != toInsert.FieldCount; ++i) {
var n = toInsert.GetName(i);
bulkCopy.ColumnMappings.Add(n, n);
}
bulkCopy.WriteToServer(toInsert);
}
}
public static void Insert(this SqlConnection connection, SqlTransaction transaction, string destinationTable, IDataReader toInsert) =>
new DataBossBulkCopy(connection, transaction).Insert(destinationTable, toInsert);

public static ICollection<int> InsertAndGetIdentities<T>(this SqlConnection connection, string destinationTable, IEnumerable<T> rows) =>
InsertAndGetIdentities(connection, null, destinationTable, rows);

public static ICollection<int> InsertAndGetIdentities<T>(this SqlConnection connection, SqlTransaction transaction, string destinationTable, IEnumerable<T> rows) {
var n = 0;
var toInsert = SequenceDataReader.Create(rows, x => {
x.Map("$", _ => ++n);
x.MapAll();
});

var scripter = new DataBossScripter();
connection.ExecuteNonQuery(transaction, $@"
{scripter.ScriptTable(TempTableName, toInsert)}
create clustered index [#$_$] on {TempTableName}([{toInsert.GetName(0)}])
");

using(var bulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.TableLock, transaction) { DestinationTableName = TempTableName })
bulkCopy.WriteToServer(toInsert);

var columns = string.Join(",", Enumerable.Range(1, toInsert.FieldCount - 1).Select(toInsert.GetName));
using(var cmd = connection.CreateCommand($@"
insert {destinationTable} with(tablock)({columns})
output inserted.$identity as {nameof(IdRow.Id)}
select {columns}
from {TempTableName}
order by [$]
drop table {TempTableName}
")) {
cmd.CommandTimeout = 0;
cmd.Transaction = transaction;
using(var reader = ObjectReader.For(cmd.ExecuteReader(CommandBehavior.SingleResult | CommandBehavior.SequentialAccess)))
return reader.Read<IdRow>().OrderBy(x => x.Id).Select(x => x.Id).ToList();
}
}
public static ICollection<int> InsertAndGetIdentities<T>(this SqlConnection connection, SqlTransaction transaction, string destinationTable, IEnumerable<T> rows) =>
new DataBossBulkCopy(connection, transaction).InsertAndGetIdentities(destinationTable, rows);

public static void WithCommand(this SqlConnection connection, Action<SqlCommand> useCommand) {
using(var cmd = connection.CreateCommand())
Expand Down
2 changes: 1 addition & 1 deletion Package-Release.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ $MSBuildPath = [IO.Directory]::GetFiles(
& $MSBuildPath DataBoss\DataBoss.sln /t:Clean /p:Configuration=Release /v:m /nologo
& $MSBuildPath Build.proj /t:Package /p:Configuration=Release /p:Build=$Build /v:m /nologo

& ./Tools/NuGet.exe pack DataBoss\DataBoss.csproj -OutputDirectory Artifacts -Properties Configuration=Release
& ./Tools/NuGet.exe pack DataBoss\DataBoss.csproj -OutputDirectory Artifacts -Properties "Configuration=Release;id=DataBoss"

0 comments on commit 3fb90f2

Please sign in to comment.