-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: new class DataSourceUrl to create DbDataSource (#790)
- Loading branch information
Showing
8 changed files
with
271 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
using DubUrl.Extensions; | ||
using DubUrl.Mapping; | ||
using DubUrl.Parsing; | ||
using DubUrl.Querying; | ||
using DubUrl.Querying.Dialects; | ||
using DubUrl.Querying.Parametrizing; | ||
using DubUrl.Querying.Reading; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Data; | ||
using System.Data.Common; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace DubUrl; | ||
|
||
public class BaseConnectionUrl | ||
{ | ||
protected record ParseResult(string ConnectionString, UrlInfo UrlInfo, IDialect Dialect, IConnectivity Connectivity, IParametrizer Parametrizer) { } | ||
private ParseResult? result; | ||
protected ParseResult Result { get => result ??= ParseDetail(); } | ||
protected SchemeMapperBuilder SchemeMapperBuilder { get; } | ||
private IMapper? Mapper { get; set; } | ||
private IParser Parser { get; } | ||
public string Url { get; } | ||
|
||
public BaseConnectionUrl(string url) | ||
: this(url, new Parser(), new SchemeMapperBuilder()) { } | ||
|
||
public BaseConnectionUrl(string url, SchemeMapperBuilder builder) | ||
: this(url, new Parser(), builder) { } | ||
|
||
internal BaseConnectionUrl(string url, IParser parser, SchemeMapperBuilder builder) | ||
=> (Url, Parser, SchemeMapperBuilder) = (url, parser, builder); | ||
|
||
protected internal DbProviderFactory GetProviderFactory() | ||
=> SchemeMapperBuilder.GetProviderFactory(Result.UrlInfo.Schemes); | ||
|
||
private ParseResult ParseDetail() | ||
{ | ||
var urlInfo = Parser.Parse(Url); | ||
SchemeMapperBuilder.Build(); | ||
Mapper = SchemeMapperBuilder.GetMapper(urlInfo.Schemes); | ||
Mapper.Rewrite(urlInfo); | ||
return new ParseResult(Mapper.GetConnectionString(), urlInfo, Mapper.GetDialect(), Mapper.GetConnectivity(), Mapper.GetParametrizer()); | ||
} | ||
|
||
public string Parse() => Result.ConnectionString; | ||
public virtual IDialect Dialect => Result.Dialect; | ||
public virtual IConnectivity Connectivity => Result.Connectivity; | ||
public virtual IParametrizer Parametrizer => Result.Parametrizer; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
using DubUrl.Extensions; | ||
using DubUrl.Mapping; | ||
using DubUrl.Parsing; | ||
using DubUrl.Querying; | ||
using DubUrl.Querying.Dialects; | ||
using DubUrl.Querying.Parametrizing; | ||
using DubUrl.Querying.Reading; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Data; | ||
using System.Data.Common; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace DubUrl; | ||
|
||
#if NET7_0_OR_GREATER | ||
public class DataSourceUrl : BaseConnectionUrl | ||
{ | ||
public DataSourceUrl(string url, SchemeMapperBuilder? builder = null) | ||
: this(url, new Parser(), builder ?? new()) { } | ||
|
||
internal DataSourceUrl(string url, IParser parser, SchemeMapperBuilder builder) | ||
: base(url, parser, builder) { } | ||
|
||
public virtual DbDataSource Create() | ||
{ | ||
var providerFactory = GetProviderFactory(); | ||
var dataSource = providerFactory.CreateDataSource(Parse()); | ||
return dataSource; | ||
} | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Data; | ||
using System.Data.Common; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using DubUrl.Mapping; | ||
using DubUrl.Parsing; | ||
using Moq; | ||
using NUnit.Framework; | ||
|
||
namespace DubUrl.Testing; | ||
|
||
#if NET7_0_OR_GREATER | ||
public class DataSourceUrlTest | ||
{ | ||
[Test] | ||
public void Parse_AnyConnectionString_OneCallToParserParse() | ||
{ | ||
var url = "mssql://localhost/db"; | ||
|
||
var parserMock = new Mock<IParser>(); | ||
parserMock.Setup(x => x.Parse(It.IsAny<string>())).Returns(new UrlInfo()); | ||
|
||
var mapperMock = new Mock<IMapper>(); | ||
mapperMock.Setup(x => x.Rewrite(It.IsAny<UrlInfo>())); | ||
|
||
var schemeMapperBuilderMock = new Mock<SchemeMapperBuilder>(); | ||
schemeMapperBuilderMock.Setup(x => x.Build()); | ||
schemeMapperBuilderMock.Setup(x => x.GetMapper(It.IsAny<string[]>())).Returns(mapperMock.Object); | ||
|
||
var dataSourceUrl = new DataSourceUrl(url, parserMock.Object, schemeMapperBuilderMock.Object); | ||
dataSourceUrl.Parse(); | ||
|
||
parserMock.Verify(x => x.Parse(url), Times.Once()); | ||
} | ||
|
||
[Test] | ||
public void Parse_AnyConnectionString_OneCallToMapperFactoryInstantiate() | ||
{ | ||
var url = "mssql://localhost/db"; | ||
|
||
var parserMock = new Mock<IParser>(); | ||
parserMock.Setup(x => x.Parse(It.IsAny<string>())).Returns(new UrlInfo() { Schemes = ["mssql"] }); | ||
|
||
var mapperMock = new Mock<IMapper>(); | ||
mapperMock.Setup(x => x.Rewrite(It.IsAny<UrlInfo>())); | ||
|
||
var schemeMapperBuilderMock = new Mock<SchemeMapperBuilder>(); | ||
schemeMapperBuilderMock.Setup(x => x.Build()); | ||
schemeMapperBuilderMock.Setup(x => x.GetMapper(It.IsAny<string[]>())).Returns(mapperMock.Object); | ||
|
||
var dataSourceUrl = new DataSourceUrl(url, parserMock.Object, schemeMapperBuilderMock.Object); | ||
dataSourceUrl.Parse(); | ||
|
||
schemeMapperBuilderMock.Verify(x => x.Build(), Times.Once()); | ||
schemeMapperBuilderMock.Verify(x => x.GetMapper(It.Is<string[]>(x => x.Length == 1 || x.First() == "mssql")), Times.AtLeastOnce()); | ||
} | ||
|
||
[Test] | ||
public void Parse_AnyConnectionString_OneCallToMapperMap() | ||
{ | ||
var url = "mssql://localhost/db"; | ||
|
||
var parserMock = new Mock<IParser>(); | ||
parserMock.Setup(x => x.Parse(It.IsAny<string>())).Returns(new UrlInfo()); | ||
|
||
var mapperMock = new Mock<IMapper>(); | ||
mapperMock.Setup(x => x.Rewrite(It.IsAny<UrlInfo>())); | ||
|
||
var schemeMapperBuilderMock = new Mock<SchemeMapperBuilder>(); | ||
schemeMapperBuilderMock.Setup(x => x.Build()); | ||
schemeMapperBuilderMock.Setup(x => x.GetMapper(It.IsAny<string[]>())).Returns(mapperMock.Object); | ||
|
||
var dataSourceUrl = new DataSourceUrl(url, parserMock.Object, schemeMapperBuilderMock.Object); | ||
dataSourceUrl.Parse(); | ||
|
||
mapperMock.Verify(x => x.Rewrite(It.IsAny<UrlInfo>()), Times.Once()); | ||
} | ||
|
||
[Test] | ||
public void Create_AnyConnectionUrl_OneCallToBuilderMethods() | ||
{ | ||
var url = "mssql://localhost/db"; | ||
|
||
var parserMock = new Mock<IParser>(); | ||
parserMock.Setup(x => x.Parse(It.IsAny<string>())).Returns(new UrlInfo()); | ||
|
||
var mapperMock = new Mock<IMapper>(); | ||
mapperMock.Setup(x => x.Rewrite(It.IsAny<UrlInfo>())); | ||
|
||
var dbProviderfactoryMock = new Mock<DbProviderFactory>(); | ||
dbProviderfactoryMock.Setup(x => x.CreateDataSource(It.IsAny<string>())).Returns(Mock.Of<DbDataSource>()); | ||
|
||
var schemeMapperBuilderMock = new Mock<SchemeMapperBuilder>(); | ||
schemeMapperBuilderMock.Setup(x => x.Build()); | ||
schemeMapperBuilderMock.Setup(x => x.GetMapper(It.IsAny<string[]>())).Returns(mapperMock.Object); | ||
schemeMapperBuilderMock.Setup(x => x.GetProviderFactory(It.IsAny<string[]>())).Returns(dbProviderfactoryMock.Object); | ||
|
||
var dataSourceUrl = new DataSourceUrl(url, parserMock.Object, schemeMapperBuilderMock.Object); | ||
dataSourceUrl.Create(); | ||
|
||
schemeMapperBuilderMock.VerifyAll(); | ||
} | ||
|
||
[Test] | ||
public void Create_AnyConnectionUrl_CreateWithExpectedConnectionString() | ||
{ | ||
var url = "mssql://localhost/db"; | ||
var connString = "Data Source=localhost;Initial Catalog=db"; | ||
|
||
var parserMock = new Mock<IParser>(); | ||
parserMock.Setup(x => x.Parse(It.IsAny<string>())).Returns(new UrlInfo()); | ||
|
||
var mapperMock = new Mock<IMapper>(); | ||
mapperMock.Setup(x => x.Rewrite(It.IsAny<UrlInfo>())); | ||
mapperMock.Setup(x => x.GetConnectionString()).Returns(connString); | ||
|
||
var dbProviderfactoryMock = new Mock<DbProviderFactory>(); | ||
dbProviderfactoryMock.Setup(x => x.CreateDataSource(connString)).Returns(Mock.Of<DbDataSource>()); | ||
|
||
var schemeMapperBuilderMock = new Mock<SchemeMapperBuilder>(); | ||
schemeMapperBuilderMock.Setup(x => x.Build()); | ||
schemeMapperBuilderMock.Setup(x => x.GetMapper(It.IsAny<string[]>())).Returns(mapperMock.Object); | ||
schemeMapperBuilderMock.Setup(x => x.GetProviderFactory(It.IsAny<string[]>())).Returns(dbProviderfactoryMock.Object); | ||
|
||
var dataSourceUrl = new DataSourceUrl(url, parserMock.Object, schemeMapperBuilderMock.Object); | ||
dataSourceUrl.Create(); | ||
|
||
dbProviderfactoryMock.Verify(x => x.CreateDataSource(connString), Times.Once()); | ||
dbProviderfactoryMock.VerifyAll(); | ||
} | ||
|
||
[Test] | ||
public void Create_AnyConnectionUrl_DbDataSourceFromDbProviderFactory() | ||
{ | ||
var url = "mssql://localhost/db"; | ||
var connString = "Data Source=localhost;Initial Catalog=db"; | ||
|
||
var parserMock = new Mock<IParser>(); | ||
parserMock.Setup(x => x.Parse(It.IsAny<string>())).Returns(new UrlInfo()); | ||
|
||
var mapperMock = new Mock<IMapper>(); | ||
mapperMock.Setup(x => x.Rewrite(It.IsAny<UrlInfo>())); | ||
mapperMock.Setup(x => x.GetConnectionString()).Returns(connString); | ||
|
||
var dbDataSource = Mock.Of<DbDataSource>(); | ||
var dbProviderfactoryMock = new Mock<DbProviderFactory>(); | ||
dbProviderfactoryMock.Setup(x => x.CreateDataSource(connString)).Returns(dbDataSource); | ||
|
||
var schemeMapperBuilderMock = new Mock<SchemeMapperBuilder>(); | ||
schemeMapperBuilderMock.Setup(x => x.Build()); | ||
schemeMapperBuilderMock.Setup(x => x.GetMapper(It.IsAny<string[]>())).Returns(mapperMock.Object); | ||
schemeMapperBuilderMock.Setup(x => x.GetProviderFactory(It.IsAny<string[]>())).Returns(dbProviderfactoryMock.Object); | ||
|
||
var dataSourceUrl = new DataSourceUrl(url, parserMock.Object, schemeMapperBuilderMock.Object); | ||
Assert.That(dataSourceUrl.Create(), Is.EqualTo(dbDataSource)); | ||
} | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters