Skip to content

Commit 62c5e60

Browse files
committed
added multiple db configurations support
1 parent 62f2850 commit 62c5e60

15 files changed

+157
-80
lines changed

Example/Data/Context.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public class Context : DbContext
2121
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
2222
{
2323
//Default: JSON-Serialize
24-
optionsBuilder.UseFileContextDatabase();
24+
//optionsBuilder.UseFileContextDatabase();
2525

2626
//optionsBuilder.UseFileContextDatabase("bson");
2727

@@ -37,6 +37,9 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
3737

3838
//Excel
3939
//optionsBuilder.UseFileContextDatabase("excel", databaseName: "test");
40+
41+
//ConnectionString
42+
optionsBuilder.UseFileContextDatabaseConnectionString("SeriAlizer=xml;databasenaMe=Test");
4043
}
4144

4245
protected override void OnModelCreating(ModelBuilder modelBuilder)

Example/Program.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ static void Main(string[] args)
2828
List<User> users2 = db.Users.Include("Contents.Entries").Include("Contents").Include("Contents").ToList();
2929

3030
List<User> user3 = db2.Users.ToList();
31+
db2.Users.RemoveRange(user3.Take(2));
32+
db2.SaveChanges();
33+
3134

3235
db.Users.RemoveRange(db.Users.Skip(40));
3336
db.SaveChanges();

FileContextCore/Extensions/FileContextDbContextOptionsExtensions.cs

Lines changed: 67 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
55

66
using System;
7+
using System.Collections.Generic;
8+
using System.Linq;
79
using FileContextCore.Diagnostics;
810
using FileContextCore.Infrastructure.Internal;
911
using FileContextCore.Infrastructure;
@@ -24,6 +26,30 @@ namespace FileContextCore
2426
/// </summary>
2527
public static class FileContextDbContextOptionsExtensions
2628
{
29+
/// <summary>
30+
/// Configures the context to connect to an in-memory database.
31+
/// The in-memory database is shared anywhere the same name is used, but only for a given
32+
/// service provider.
33+
/// </summary>
34+
/// <typeparam name="TContext"> The type of context being configured. </typeparam>
35+
/// <param name="optionsBuilder"> The builder being used to configure the context. </param>
36+
/// <param name="connectionString">A connection string that is used to build the options</param>
37+
/// <param name="databaseRoot">
38+
/// All in-memory databases will be rooted in this object, allowing the application
39+
/// to control their lifetime. This is useful when sometimes the context instance
40+
/// is created explicitly with <c>new</c> while at other times it is resolved using dependency injection.
41+
/// </param>
42+
/// <param name="inMemoryOptionsAction">An optional action to allow additional in-memory specific configuration.</param>
43+
/// <returns> The options builder so that further configuration can be chained. </returns>
44+
public static DbContextOptionsBuilder<TContext> UseFileContextDatabaseConnectionString<TContext>(
45+
[NotNull] this DbContextOptionsBuilder<TContext> optionsBuilder,
46+
string connectionString,
47+
[CanBeNull] FileContextDatabaseRoot databaseRoot = null,
48+
[CanBeNull] Action<FileContextDbContextOptionsBuilder> inMemoryOptionsAction = null)
49+
where TContext : DbContext
50+
=> (DbContextOptionsBuilder<TContext>)UseFileContextDatabaseConnectionString(
51+
(DbContextOptionsBuilder)optionsBuilder, connectionString, databaseRoot, inMemoryOptionsAction);
52+
2753
/// <summary>
2854
/// Configures the context to connect to an in-memory database.
2955
/// The in-memory database is shared anywhere the same name is used, but only for a given
@@ -63,21 +89,53 @@ public static DbContextOptionsBuilder<TContext> UseFileContextDatabase<TContext>
6389
/// service provider.
6490
/// </summary>
6591
/// <param name="optionsBuilder"> The builder being used to configure the context. </param>
66-
/// <param name="databaseName">
67-
/// The name of the in-memory database. This allows the scope of the in-memory database to be controlled
68-
/// independently of the context. The in-memory database is shared anywhere the same name is used.
69-
/// </param>
70-
/// <param name="location">An optional parameter to define the location where the files are stored</param>
92+
/// <param name="connectionString">A connection string that is used to build the options</param>
7193
/// <param name="databaseRoot">
7294
/// All in-memory databases will be rooted in this object, allowing the application
7395
/// to control their lifetime. This is useful when sometimes the context instance
7496
/// is created explicitly with <c>new</c> while at other times it is resolved using dependency injection.
7597
/// </param>
7698
/// <param name="inMemoryOptionsAction">An optional action to allow additional in-memory specific configuration.</param>
77-
/// <param name="serializer">The serializer to be used. Defaults to json</param>
78-
/// <param name="filemanager">The file manager to be used.</param>
7999
/// <returns> The options builder so that further configuration can be chained. </returns>
80-
public static DbContextOptionsBuilder UseFileContextDatabase(
100+
public static DbContextOptionsBuilder UseFileContextDatabaseConnectionString(
101+
[NotNull] this DbContextOptionsBuilder optionsBuilder,
102+
string connectionString,
103+
[CanBeNull] FileContextDatabaseRoot databaseRoot = null,
104+
[CanBeNull] Action<FileContextDbContextOptionsBuilder> inMemoryOptionsAction = null)
105+
{
106+
string[] connectionStringParts = connectionString.Split(';');
107+
Dictionary<string, string> connectionStringSplitted = connectionStringParts
108+
.Select(segment => segment.Split('='))
109+
.ToDictionary(parts => parts[0].Trim().ToLowerInvariant(), parts => parts[1].Trim());
110+
111+
return UseFileContextDatabase(optionsBuilder,
112+
connectionStringSplitted.GetValueOrDefault("serializer"),
113+
connectionStringSplitted.GetValueOrDefault("filemanager"),
114+
connectionStringSplitted.GetValueOrDefault("databasename"),
115+
connectionStringSplitted.GetValueOrDefault("location"), databaseRoot, inMemoryOptionsAction);
116+
}
117+
118+
/// <summary>
119+
/// Configures the context to connect to a named in-memory database.
120+
/// The in-memory database is shared anywhere the same name is used, but only for a given
121+
/// service provider.
122+
/// </summary>
123+
/// <param name="optionsBuilder"> The builder being used to configure the context. </param>
124+
/// <param name="databaseName">
125+
/// The name of the in-memory database. This allows the scope of the in-memory database to be controlled
126+
/// independently of the context. The in-memory database is shared anywhere the same name is used.
127+
/// </param>
128+
/// <param name="location">An optional parameter to define the location where the files are stored</param>
129+
/// <param name="databaseRoot">
130+
/// All in-memory databases will be rooted in this object, allowing the application
131+
/// to control their lifetime. This is useful when sometimes the context instance
132+
/// is created explicitly with <c>new</c> while at other times it is resolved using dependency injection.
133+
/// </param>
134+
/// <param name="inMemoryOptionsAction">An optional action to allow additional in-memory specific configuration.</param>
135+
/// <param name="serializer">The serializer to be used. Defaults to json</param>
136+
/// <param name="filemanager">The file manager to be used.</param>
137+
/// <returns> The options builder so that further configuration can be chained. </returns>
138+
public static DbContextOptionsBuilder UseFileContextDatabase(
81139
[NotNull] this DbContextOptionsBuilder optionsBuilder,
82140
string serializer = "json",
83141
string filemanager = "default",
@@ -91,8 +149,7 @@ public static DbContextOptionsBuilder UseFileContextDatabase(
91149
var extension = optionsBuilder.Options.FindExtension<FileContextOptionsExtension>()
92150
?? new FileContextOptionsExtension();
93151

94-
extension = extension.WithStoreName(databaseName);
95-
extension = extension.WithCustomOptions(serializer, filemanager, location);
152+
extension = extension.WithCustomOptions(databaseName, serializer, filemanager, location);
96153

97154
if (databaseRoot != null)
98155
{

FileContextCore/Extensions/FileContextServiceCollectionExtensions.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public static class FileContextServiceCollectionExtensions
4545
/// <returns>
4646
/// The same service collection so that multiple calls can be chained.
4747
/// </returns>
48-
public static IServiceCollection AddEntityFrameworkFileContextDatabase([NotNull] this IServiceCollection serviceCollection, FileContextOptionsExtension optionsExtension = null)
48+
public static IServiceCollection AddEntityFrameworkFileContextDatabase([NotNull] this IServiceCollection serviceCollection)
4949
{
5050
Check.NotNull(serviceCollection, nameof(serviceCollection));
5151

@@ -69,9 +69,7 @@ public static IServiceCollection AddEntityFrameworkFileContextDatabase([NotNull]
6969
.TryAddProviderSpecificServices(
7070
b => b
7171
.TryAddSingleton<IFileContextSingletonOptions, FileContextSingletonOptions>()
72-
.TryAddScoped<IFileContextScopedOptions, FileContextScopedOptions>((serviceProvider) => new FileContextScopedOptions(optionsExtension))
7372
.TryAddSingleton<IFileContextStoreCache, FileContextStoreCache>()
74-
.TryAddSingleton<IFileContextTableFactory, FileContextTableFactory>()
7573
.TryAddScoped<IFileContextDatabase, FileContextDatabase>());
7674

7775
builder.TryAddCoreServices();

FileContextCore/FileContextCore.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<SignAssembly Condition="'$(OS)' == 'Windows_NT'">true</SignAssembly>
66
<AssemblyOriginatorKeyFile>FileContextCoreCert.pfx</AssemblyOriginatorKeyFile>
77
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
8-
<Version>3.2.0</Version>
8+
<Version>3.2.1</Version>
99
<Company>morrisjdev</Company>
1010
<Authors>morrisjdev</Authors>
1111
<Description>File provider for Entity Framework Core (to be used for development purposes)</Description>
@@ -19,8 +19,8 @@
1919
<PackageProjectUrl>https://github.com/morrisjdev/FileContextCore</PackageProjectUrl>
2020
<NeutralLanguage>en-US</NeutralLanguage>
2121
<DelaySign>false</DelaySign>
22-
<AssemblyVersion>3.2.0.0</AssemblyVersion>
23-
<FileVersion>3.2.0.0</FileVersion>
22+
<AssemblyVersion>3.2.1.0</AssemblyVersion>
23+
<FileVersion>3.2.1.0</FileVersion>
2424
</PropertyGroup>
2525

2626
<ItemGroup>

FileContextCore/Infrastructure/Internal/FileContextOptionsExtension.cs

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,9 @@ namespace FileContextCore.Infrastructure.Internal
2222
/// </summary>
2323
public class FileContextOptionsExtension : IDbContextOptionsExtension
2424
{
25-
private string _storeName;
26-
public string serializer;
27-
public string filemanager;
28-
public string location;
2925
private FileContextDatabaseRoot _databaseRoot;
3026
private DbContextOptionsExtensionInfo _info;
27+
private FileContextScopedOptions _options;
3128

3229
/// <summary>
3330
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
@@ -37,6 +34,7 @@ public class FileContextOptionsExtension : IDbContextOptionsExtension
3734
/// </summary>
3835
public FileContextOptionsExtension()
3936
{
37+
_options = new FileContextScopedOptions(null, null, null, null);
4038
}
4139

4240
/// <summary>
@@ -47,11 +45,7 @@ public FileContextOptionsExtension()
4745
/// </summary>
4846
protected FileContextOptionsExtension([NotNull] FileContextOptionsExtension copyFrom)
4947
{
50-
serializer = copyFrom.serializer;
51-
filemanager = copyFrom.filemanager;
52-
location = copyFrom.location;
53-
54-
_storeName = copyFrom._storeName;
48+
_options = (FileContextScopedOptions)copyFrom._options.Clone();
5549
_databaseRoot = copyFrom._databaseRoot;
5650
}
5751

@@ -78,36 +72,21 @@ public virtual DbContextOptionsExtensionInfo Info
7872
/// any release. You should only use it directly in your code with extreme caution and knowing that
7973
/// doing so can result in application failures when updating to a new Entity Framework Core release.
8074
/// </summary>
81-
public virtual string StoreName => _storeName;
75+
public virtual FileContextScopedOptions Options => _options;
8276

8377
/// <summary>
8478
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
8579
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
8680
/// any release. You should only use it directly in your code with extreme caution and knowing that
8781
/// doing so can result in application failures when updating to a new Entity Framework Core release.
8882
/// </summary>
89-
public virtual FileContextOptionsExtension WithStoreName([NotNull] string storeName)
83+
public virtual FileContextOptionsExtension WithCustomOptions(string databaseName, string serializer, string fileManager, string location)
9084
{
9185
var clone = Clone();
92-
93-
clone._storeName = storeName;
94-
95-
return clone;
96-
}
97-
98-
/// <summary>
99-
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
100-
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
101-
/// any release. You should only use it directly in your code with extreme caution and knowing that
102-
/// doing so can result in application failures when updating to a new Entity Framework Core release.
103-
/// </summary>
104-
public virtual FileContextOptionsExtension WithCustomOptions(string serializer, string filemanager, string location)
105-
{
106-
var clone = Clone();
107-
108-
clone.serializer = serializer;
109-
clone.filemanager = filemanager;
110-
clone.location = location;
86+
clone._options.Location = location;
87+
clone._options.DatabaseName = databaseName;
88+
clone._options.FileManager = fileManager;
89+
clone._options.Serializer = serializer;
11190

11291
return clone;
11392
}
@@ -143,7 +122,7 @@ public virtual FileContextOptionsExtension WithDatabaseRoot([NotNull] FileContex
143122
/// </summary>
144123
public virtual void ApplyServices(IServiceCollection services)
145124
{
146-
services.AddEntityFrameworkFileContextDatabase(this);
125+
services.AddEntityFrameworkFileContextDatabase();
147126
}
148127

149128
/// <summary>
@@ -178,7 +157,10 @@ public override string LogFragment
178157
{
179158
var builder = new StringBuilder();
180159

181-
builder.Append("StoreName=").Append(Extension._storeName).Append(' ');
160+
builder.Append("Location=").Append(Extension.Options.Location).Append(' ');
161+
builder.Append("DatabaseName=").Append(Extension.Options.DatabaseName).Append(' ');
162+
builder.Append("Serializer=").Append(Extension.Options.Serializer).Append(' ');
163+
builder.Append("FileManager=").Append(Extension.Options.FileManager).Append(' ');
182164

183165
_logFragment = builder.ToString();
184166
}

FileContextCore/Infrastructure/Internal/FileContextScopedOptions.cs

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,44 @@
55

66
namespace FileContextCore.Infrastructure.Internal
77
{
8-
public class FileContextScopedOptions : IFileContextScopedOptions
8+
public class FileContextScopedOptions : IFileContextScopedOptions, ICloneable
99
{
10-
public FileContextScopedOptions(FileContextOptionsExtension options)
10+
public FileContextScopedOptions(string databaseName, string serializer, string fileManager, string location)
1111
{
12-
if (options != null)
13-
{
14-
Serializer = options.serializer;
15-
DatabaseName = options.StoreName;
16-
FileManager = options.filemanager;
17-
Location = options.location;
18-
}
12+
Serializer = serializer;
13+
DatabaseName = databaseName;
14+
FileManager = fileManager;
15+
Location = location;
1916
}
2017

21-
public virtual string DatabaseName { get; private set; }
18+
public string DatabaseName { get; set; }
19+
20+
public string Serializer { get; set; }
21+
22+
public string FileManager { get; set; }
23+
24+
public string Location { get; set; }
25+
26+
public override int GetHashCode()
27+
{
28+
return (DatabaseName + Serializer + FileManager + Location).GetHashCode();
29+
}
2230

23-
public virtual string Serializer { get; private set; }
31+
public object Clone()
32+
{
33+
return new FileContextScopedOptions(DatabaseName, Serializer, FileManager, Location);
34+
}
2435

25-
public virtual string FileManager { get; private set; }
36+
public override bool Equals(object obj)
37+
{
38+
if (obj == null)
39+
{
40+
return false;
41+
}
2642

27-
public virtual string Location { get; private set; }
43+
FileContextScopedOptions optionsCompare = (FileContextScopedOptions) obj;
44+
return optionsCompare.Serializer == Serializer && optionsCompare.DatabaseName == DatabaseName &&
45+
optionsCompare.FileManager == FileManager && optionsCompare.Location == Location;
46+
}
2847
}
2948
}

FileContextCore/Metadata/Conventions/FileContextConventionSetBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public static ConventionSet Build()
5252
var serviceProvider = new ServiceCollection()
5353
.AddEntityFrameworkFileContextDatabase()
5454
.AddDbContext<DbContext>((p, o) =>
55-
o.UseFileContextDatabase(Guid.NewGuid().ToString())
55+
o.UseFileContextDatabase(databaseName: Guid.NewGuid().ToString())
5656
.UseInternalServiceProvider(p))
5757
.BuildServiceProvider();
5858

FileContextCore/Serializer/EXCELSerializer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ public EXCELSerializer(IEntityType _entityType, string _password, string databas
9999

100100
public Dictionary<TKey, object[]> Deserialize<TKey>(Dictionary<TKey, object[]> newList)
101101
{
102-
for (int y = 2; y < worksheet.Dimension.Rows; y++)
102+
for (int y = 2; y <= worksheet.Dimension.Rows; y++)
103103
{
104104
List<object> value = new List<object>();
105105

@@ -156,7 +156,7 @@ private void FillRows<TKey>(Dictionary<TKey, object[]> list)
156156

157157
private void DeleteUnusedRows(int lastRow)
158158
{
159-
if (worksheet.Dimension.Rows > lastRow)
159+
if (worksheet.Dimension.Rows >= lastRow)
160160
{
161161
int count = worksheet.Dimension.Rows - lastRow;
162162
worksheet.DeleteRow(lastRow + 1, count);

0 commit comments

Comments
 (0)