-
-
- # Sheetly
-
- **Entity Framework Core for Google Sheets** β The familiar ORM experience you love, now for spreadsheets.
-
- [](https://www.nuget.org/packages/Sheetly.Core/)
- [](https://opensource.org/licenses/MIT)
-
+
+
+
+
+
+
+
+
+
+
---
diff --git a/assets/banner.svg b/assets/banner.svg
new file mode 100644
index 0000000..546175e
--- /dev/null
+++ b/assets/banner.svg
@@ -0,0 +1,20 @@
+
diff --git a/assets/icon.png b/assets/icon.png
new file mode 100644
index 0000000..bc49536
Binary files /dev/null and b/assets/icon.png differ
diff --git a/BREAKING_CHANGES.md b/docs/BREAKING_CHANGES.md
similarity index 100%
rename from BREAKING_CHANGES.md
rename to docs/BREAKING_CHANGES.md
diff --git a/RELEASE_NOTES.md b/docs/RELEASE_NOTES.md
similarity index 79%
rename from RELEASE_NOTES.md
rename to docs/RELEASE_NOTES.md
index 9ca63e9..bf189c1 100644
--- a/RELEASE_NOTES.md
+++ b/docs/RELEASE_NOTES.md
@@ -1,4 +1,4 @@
-# π Sheetly v1.0.0 β Release Notes
+# π Sheetly v1.0.1 β Release Notes
## Entity Framework Core for Google Sheets
@@ -6,6 +6,17 @@
---
+## π What's Fixed in v1.0.1
+
+- **CLI banner** β EF Core-style terminal output with teal rocket art
+- **`OnConfiguring` detection** β `dotnet sheetly database update` now reads connection settings directly from `OnConfiguring()`, no `appsettings.json` required
+- **Build-first behavior** β All CLI commands now build the project before executing (like `dotnet ef`)
+- **Version output** β Removed git commit hash from `--version` output
+- **Brand logo** β Added official icon to all NuGet packages
+- **CI/CD** β GitHub Actions workflows for automatic NuGet publishing
+
+---
+
## β¨ What's New
### Core Features
diff --git a/dotnet-tools.json b/dotnet-tools.json
deleted file mode 100644
index b0e38ab..0000000
--- a/dotnet-tools.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "version": 1,
- "isRoot": true,
- "tools": {}
-}
\ No newline at end of file
diff --git a/icon.png b/icon.png
deleted file mode 100644
index b1f6ef2..0000000
Binary files a/icon.png and /dev/null differ
diff --git a/samples/Sheetly.Sample/MySheetsContext.cs b/samples/Sheetly.Sample/AppDbContext.cs
similarity index 100%
rename from samples/Sheetly.Sample/MySheetsContext.cs
rename to samples/Sheetly.Sample/AppDbContext.cs
diff --git a/samples/Sheetly.Sample/Migrations/20260222142948_InitialCreate.cs b/samples/Sheetly.Sample/Migrations/20260222142948_InitialCreate.cs
index 36f8398..6c1c7bf 100644
--- a/samples/Sheetly.Sample/Migrations/20260222142948_InitialCreate.cs
+++ b/samples/Sheetly.Sample/Migrations/20260222142948_InitialCreate.cs
@@ -1,34 +1,33 @@
using Sheetly.Core.Migrations;
-using Sheetly.Core.Migrations.Operations;
namespace Sheetly.Sample.Migrations;
[Migration("20260222142948_InitialCreate")]
public partial class InitialCreate : Migration
{
- public override void Up(MigrationBuilder builder)
- {
- // ClassName: Category
- builder.CreateTable("Categories", table => table
- .Column("Id", c => c.IsPrimaryKey().IsUnique())
- .Column("Name")
- );
+ public override void Up(MigrationBuilder builder)
+ {
+ // ClassName: Category
+ builder.CreateTable("Categories", table => table
+ .Column("Id", c => c.IsPrimaryKey().IsUnique())
+ .Column("Name")
+ );
- // ClassName: Product
- builder.CreateTable("Products", table => table
- .Column("Id", c => c.IsPrimaryKey().IsUnique())
- .Column("Title")
- .Column("Price", c => c.IsRequired())
- .Column("Description")
- .Column("Stock", c => c.IsRequired())
- .Column("CategoryId", c => c.IsRequired().IsForeignKey("Categories"))
- );
+ // ClassName: Product
+ builder.CreateTable("Products", table => table
+ .Column("Id", c => c.IsPrimaryKey().IsUnique())
+ .Column("Title")
+ .Column("Price", c => c.IsRequired())
+ .Column("Description")
+ .Column("Stock", c => c.IsRequired())
+ .Column("CategoryId", c => c.IsRequired().IsForeignKey("Categories"))
+ );
- }
+ }
- public override void Down(MigrationBuilder builder)
- {
- builder.DropTable("Products");
- builder.DropTable("Categories");
- }
+ public override void Down(MigrationBuilder builder)
+ {
+ builder.DropTable("Products");
+ builder.DropTable("Categories");
+ }
}
diff --git a/samples/Sheetly.Sample/Migrations/AppDbModelSnapshot.cs b/samples/Sheetly.Sample/Migrations/AppDbModelSnapshot.cs
index 26f6894..8b27cb2 100644
--- a/samples/Sheetly.Sample/Migrations/AppDbModelSnapshot.cs
+++ b/samples/Sheetly.Sample/Migrations/AppDbModelSnapshot.cs
@@ -1,149 +1,148 @@
-using System;
using Sheetly.Core.Migration;
namespace Sheetly.Sample.Migrations;
public partial class AppDbModelSnapshot : MigrationSnapshot
{
- public AppDbModelSnapshot()
- {
- var snapshot = BuildModel();
- this.Entities = snapshot.Entities;
- this.ModelHash = snapshot.ModelHash;
- this.Version = snapshot.Version;
- this.LastUpdated = snapshot.LastUpdated;
- }
+ public AppDbModelSnapshot()
+ {
+ var snapshot = BuildModel();
+ this.Entities = snapshot.Entities;
+ this.ModelHash = snapshot.ModelHash;
+ this.Version = snapshot.Version;
+ this.LastUpdated = snapshot.LastUpdated;
+ }
- public static MigrationSnapshot BuildModel()
- {
- var snapshot = new MigrationSnapshot
- {
- ModelHash = "bwhvOP7ZTBivUrr39R2aR3SRrkfWllxn7VpK5f1bucg=",
- Version = "1.0.0",
- LastUpdated = DateTime.Parse("2026-02-22T14:29:48.7373255Z")
- };
+ public static MigrationSnapshot BuildModel()
+ {
+ var snapshot = new MigrationSnapshot
+ {
+ ModelHash = "bwhvOP7ZTBivUrr39R2aR3SRrkfWllxn7VpK5f1bucg=",
+ Version = "1.0.0",
+ LastUpdated = DateTime.Parse("2026-02-22T14:29:48.7373255Z")
+ };
- // Category
- snapshot.Entities["Categories"] = new EntitySchema
- {
- TableName = "Categories",
- ClassName = "Category",
- Namespace = "Sheetly.Sample.Models",
- Columns = new List
- {
- new ColumnSchema
- {
- Name = "Id",
- PropertyName = "Id",
- DataType = "Int64",
- IsPrimaryKey = true,
- IsAutoIncrement = true,
- IsForeignKey = false,
- ForeignKeyColumn = "Id",
- IsNullable = false,
- IsRequired = false
- },
- new ColumnSchema
- {
- Name = "Name",
- PropertyName = "Name",
- DataType = "String",
- IsPrimaryKey = false,
- IsAutoIncrement = false,
- IsForeignKey = false,
- ForeignKeyColumn = "Id",
- IsNullable = true,
- IsRequired = false
- }
- },
- Relationships = new List()
- };
+ // Category
+ snapshot.Entities["Categories"] = new EntitySchema
+ {
+ TableName = "Categories",
+ ClassName = "Category",
+ Namespace = "Sheetly.Sample.Models",
+ Columns = new List
+ {
+ new ColumnSchema
+ {
+ Name = "Id",
+ PropertyName = "Id",
+ DataType = "Int64",
+ IsPrimaryKey = true,
+ IsAutoIncrement = true,
+ IsForeignKey = false,
+ ForeignKeyColumn = "Id",
+ IsNullable = false,
+ IsRequired = false
+ },
+ new ColumnSchema
+ {
+ Name = "Name",
+ PropertyName = "Name",
+ DataType = "String",
+ IsPrimaryKey = false,
+ IsAutoIncrement = false,
+ IsForeignKey = false,
+ ForeignKeyColumn = "Id",
+ IsNullable = true,
+ IsRequired = false
+ }
+ },
+ Relationships = new List()
+ };
- // Product
- snapshot.Entities["Products"] = new EntitySchema
- {
- TableName = "Products",
- ClassName = "Product",
- Namespace = "Sheetly.Sample.Models",
- Columns = new List
- {
- new ColumnSchema
- {
- Name = "Id",
- PropertyName = "Id",
- DataType = "Int32",
- IsPrimaryKey = true,
- IsAutoIncrement = true,
- IsForeignKey = false,
- ForeignKeyColumn = "Id",
- IsNullable = false,
- IsRequired = false
- },
- new ColumnSchema
- {
- Name = "Title",
- PropertyName = "Title",
- DataType = "String",
- IsPrimaryKey = false,
- IsAutoIncrement = false,
- IsForeignKey = false,
- ForeignKeyColumn = "Id",
- IsNullable = true,
- IsRequired = false
- },
- new ColumnSchema
- {
- Name = "Price",
- PropertyName = "Price",
- DataType = "Decimal",
- IsPrimaryKey = false,
- IsAutoIncrement = false,
- IsForeignKey = false,
- ForeignKeyColumn = "Id",
- IsNullable = false,
- IsRequired = false
- },
- new ColumnSchema
- {
- Name = "Description",
- PropertyName = "Description",
- DataType = "String",
- IsPrimaryKey = false,
- IsAutoIncrement = false,
- IsForeignKey = false,
- ForeignKeyColumn = "Id",
- IsNullable = true,
- IsRequired = false
- },
- new ColumnSchema
- {
- Name = "Stock",
- PropertyName = "Stock",
- DataType = "Int32",
- IsPrimaryKey = false,
- IsAutoIncrement = false,
- IsForeignKey = false,
- ForeignKeyColumn = "Id",
- IsNullable = false,
- IsRequired = false
- },
- new ColumnSchema
- {
- Name = "CategoryId",
- PropertyName = "CategoryId",
- DataType = "Int32",
- IsPrimaryKey = false,
- IsAutoIncrement = false,
- IsForeignKey = true,
- ForeignKeyTable = "Categories",
- ForeignKeyColumn = "Id",
- IsNullable = false,
- IsRequired = false
- }
- },
- Relationships = new List()
- };
+ // Product
+ snapshot.Entities["Products"] = new EntitySchema
+ {
+ TableName = "Products",
+ ClassName = "Product",
+ Namespace = "Sheetly.Sample.Models",
+ Columns = new List
+ {
+ new ColumnSchema
+ {
+ Name = "Id",
+ PropertyName = "Id",
+ DataType = "Int32",
+ IsPrimaryKey = true,
+ IsAutoIncrement = true,
+ IsForeignKey = false,
+ ForeignKeyColumn = "Id",
+ IsNullable = false,
+ IsRequired = false
+ },
+ new ColumnSchema
+ {
+ Name = "Title",
+ PropertyName = "Title",
+ DataType = "String",
+ IsPrimaryKey = false,
+ IsAutoIncrement = false,
+ IsForeignKey = false,
+ ForeignKeyColumn = "Id",
+ IsNullable = true,
+ IsRequired = false
+ },
+ new ColumnSchema
+ {
+ Name = "Price",
+ PropertyName = "Price",
+ DataType = "Decimal",
+ IsPrimaryKey = false,
+ IsAutoIncrement = false,
+ IsForeignKey = false,
+ ForeignKeyColumn = "Id",
+ IsNullable = false,
+ IsRequired = false
+ },
+ new ColumnSchema
+ {
+ Name = "Description",
+ PropertyName = "Description",
+ DataType = "String",
+ IsPrimaryKey = false,
+ IsAutoIncrement = false,
+ IsForeignKey = false,
+ ForeignKeyColumn = "Id",
+ IsNullable = true,
+ IsRequired = false
+ },
+ new ColumnSchema
+ {
+ Name = "Stock",
+ PropertyName = "Stock",
+ DataType = "Int32",
+ IsPrimaryKey = false,
+ IsAutoIncrement = false,
+ IsForeignKey = false,
+ ForeignKeyColumn = "Id",
+ IsNullable = false,
+ IsRequired = false
+ },
+ new ColumnSchema
+ {
+ Name = "CategoryId",
+ PropertyName = "CategoryId",
+ DataType = "Int32",
+ IsPrimaryKey = false,
+ IsAutoIncrement = false,
+ IsForeignKey = true,
+ ForeignKeyTable = "Categories",
+ ForeignKeyColumn = "Id",
+ IsNullable = false,
+ IsRequired = false
+ }
+ },
+ Relationships = new List()
+ };
- return snapshot;
- }
+ return snapshot;
+ }
}
diff --git a/src/Sheetly.CLI/Commands/AddCommand.cs b/src/Sheetly.CLI/Commands/AddCommand.cs
index 4ee4cc0..73877da 100644
--- a/src/Sheetly.CLI/Commands/AddCommand.cs
+++ b/src/Sheetly.CLI/Commands/AddCommand.cs
@@ -1,4 +1,4 @@
-ο»Ώusing Sheetly.CLI.Helpers;
+using Sheetly.CLI.Helpers;
using Sheetly.Core;
using Sheetly.Core.Migration;
using Sheetly.Core.Migrations;
@@ -61,7 +61,6 @@ private async Task ExecuteAsync(string? name, bool noBuild, string? projectPath,
// Build current snapshot β must include fluent API metadata to match SheetsContext.InitializeAsync
var currentSnapshot = SnapshotBuilder.BuildFromContext(contextType, modelBuilder.GetMetadata());
- // Load previous snapshot from C# ModelSnapshot class (EF Core style)
string finalPath = Path.Combine(contextProjectDir, outputDir);
Directory.CreateDirectory(finalPath);
@@ -76,7 +75,6 @@ private async Task ExecuteAsync(string? name, bool noBuild, string? projectPath,
previousSnapshot = Activator.CreateInstance(snapshotType) as MigrationSnapshot;
}
- // Get differences
var modelDiffer = new ModelDiffer();
var operations = modelDiffer.GetDifferences(previousSnapshot, currentSnapshot);
@@ -87,7 +85,6 @@ private async Task ExecuteAsync(string? name, bool noBuild, string? projectPath,
}
- // Check for duplicate migration name (same class name, different timestamp)
var existingMigration = Directory.GetFiles(finalPath, "*.cs")
.Where(f => !f.Contains("ModelSnapshot"))
.FirstOrDefault(f => Path.GetFileNameWithoutExtension(f).EndsWith($"_{name}", StringComparison.OrdinalIgnoreCase));
@@ -98,7 +95,6 @@ private async Task ExecuteAsync(string? name, bool noBuild, string? projectPath,
return;
}
- // Generate C# migration file
string timestamp = DateTime.UtcNow.ToString("yyyyMMddHHmmss");
string migrationId = $"{timestamp}_{name}";
string targetNamespace = $"{contextType.Namespace}.Migrations";
@@ -106,11 +102,9 @@ private async Task ExecuteAsync(string? name, bool noBuild, string? projectPath,
var generator = new CSharpMigrationGenerator();
string migrationCode = generator.GenerateMigration(name, migrationId, targetNamespace, operations);
- // Write C# migration file
string csharpFileName = $"{migrationId}.cs";
await File.WriteAllTextAsync(Path.Combine(finalPath, csharpFileName), migrationCode, ct);
- // Generate ModelSnapshot.cs (EF Core style - C# only, no JSON!)
var snapshotGenerator = new ModelSnapshotGenerator();
string snapshotCode = snapshotGenerator.GenerateModelSnapshot(
currentSnapshot,
diff --git a/src/Sheetly.CLI/Commands/RemoveCommand.cs b/src/Sheetly.CLI/Commands/RemoveCommand.cs
index ff83882..7f74355 100644
--- a/src/Sheetly.CLI/Commands/RemoveCommand.cs
+++ b/src/Sheetly.CLI/Commands/RemoveCommand.cs
@@ -1,4 +1,4 @@
-ο»Ώusing Sheetly.CLI.Helpers;
+using Sheetly.CLI.Helpers;
using Sheetly.Core.Migration;
using Sheetly.Core.Migrations;
using Sheetly.Core.Migrations.Design;
@@ -41,7 +41,6 @@ private async Task ExecuteAsync(string? projectPath, CancellationToken ct)
return;
}
- // Find last migration type by MigrationAttribute ID (sorted descending)
var migrationTypes = assembly.GetExportedTypes()
.Where(t => t.GetCustomAttribute() != null)
.OrderByDescending(t => t.GetCustomAttribute()!.Id)
@@ -56,7 +55,6 @@ private async Task ExecuteAsync(string? projectPath, CancellationToken ct)
var lastMigrationType = migrationTypes[0];
string migrationId = lastMigrationType.GetCustomAttribute()!.Id;
- // Find the corresponding .cs file on disk
var migrationFile = Directory.GetFiles(migrationsDir, "*.cs")
.FirstOrDefault(f => !f.Contains("ModelSnapshot") &&
Path.GetFileNameWithoutExtension(f) == migrationId);
@@ -67,7 +65,6 @@ private async Task ExecuteAsync(string? projectPath, CancellationToken ct)
return;
}
- // Load the current snapshot from the compiled assembly
string contextName = contextType.Name.Replace("Context", "");
string snapshotClassName = $"{contextName}ModelSnapshot";
string targetNamespace = $"{contextType.Namespace}.Migrations";
@@ -79,17 +76,14 @@ private async Task ExecuteAsync(string? projectPath, CancellationToken ct)
var currentSnapshot = Activator.CreateInstance(snapshotType) as MigrationSnapshot
?? throw new Exception("Failed to instantiate ModelSnapshot.");
- // Get the Down() operations to know what to revert
var lastMigration = Activator.CreateInstance(lastMigrationType) as Migration
?? throw new Exception("Failed to instantiate migration.");
var downBuilder = new Sheetly.Core.Migrations.MigrationBuilder();
lastMigration.Down(downBuilder);
- // Apply Down operations to produce the previous snapshot state
var revertedSnapshot = RevertSnapshot(currentSnapshot, downBuilder.GetOperations());
- // Regenerate ModelSnapshot C# file
var generator = new ModelSnapshotGenerator();
string snapshotCode = generator.GenerateModelSnapshot(revertedSnapshot, targetNamespace, contextName);
string snapshotFilePath = Path.Combine(migrationsDir, $"{snapshotClassName}.cs");
diff --git a/src/Sheetly.CLI/Commands/UpdateCommand.cs b/src/Sheetly.CLI/Commands/UpdateCommand.cs
index d44d4ad..9e8935a 100644
--- a/src/Sheetly.CLI/Commands/UpdateCommand.cs
+++ b/src/Sheetly.CLI/Commands/UpdateCommand.cs
@@ -78,7 +78,6 @@ private async Task ExecuteAsync(bool noBuild, string? projectPath, CancellationT
Console.WriteLine($"π Found {pendingMigrations.Count} pending migration(s).");
- // Load snapshot to enrich operations with ClassName / IsAutoIncrement
var snapshotType = assembly.GetTypes()
.FirstOrDefault(t => t.Name.EndsWith("ModelSnapshot") && t.IsSubclassOf(typeof(MigrationSnapshot)));
MigrationSnapshot? currentSnapshot = snapshotType != null
diff --git a/src/Sheetly.CLI/Program.cs b/src/Sheetly.CLI/Program.cs
index d1d3f9d..f9a5e5a 100644
--- a/src/Sheetly.CLI/Program.cs
+++ b/src/Sheetly.CLI/Program.cs
@@ -3,9 +3,9 @@
using System.Reflection;
var version = Assembly
- .GetExecutingAssembly()
- .GetCustomAttribute()!
- .InformationalVersion;
+ .GetExecutingAssembly()
+ .GetCustomAttribute()!
+ .InformationalVersion;
// Root Command
RootCommand rootCommand = new("Sheetly CLI - Google Sheets ORM Tool");
diff --git a/src/Sheetly.CLI/Sheetly.CLI.csproj b/src/Sheetly.CLI/Sheetly.CLI.csproj
index 5aafdb8..1d6b1bc 100644
--- a/src/Sheetly.CLI/Sheetly.CLI.csproj
+++ b/src/Sheetly.CLI/Sheetly.CLI.csproj
@@ -9,7 +9,7 @@
dotnet-sheetlydotnet-sheetly
- 1.0.1
+ 1.0.2DotnetologMuqimjon MamadaliyevCopyright (c) 2025β2026 Muqimjon Mamadaliyev
@@ -27,7 +27,7 @@
-
+
diff --git a/src/Sheetly.CLI/icon.png b/src/Sheetly.CLI/icon.png
new file mode 100644
index 0000000..bc49536
Binary files /dev/null and b/src/Sheetly.CLI/icon.png differ
diff --git a/src/Sheetly.CLI/tools/Add-SheetlyMigration.ps1 b/src/Sheetly.CLI/tools/Add-SheetlyMigration.ps1
deleted file mode 100644
index dffc49b..0000000
--- a/src/Sheetly.CLI/tools/Add-SheetlyMigration.ps1
+++ /dev/null
@@ -1,21 +0,0 @@
-ο»Ώ<#
-.SYNOPSIS
- Yangi Sheetly migratsiyasini yaratadi.
-.PARAMETER Name
- Migratsiya nomi.
-#>
-param(
- [Parameter(Mandatory=$true, Position=0)]
- [string]$Name
-)
-
-Write-Host "π Sheetly: Yangi migratsiya yaratilmoqda: $Name..." -ForegroundColor Cyan
-
-# dotnet tool orqali asosiy CLI ni chaqiramiz
-dotnet sheetly migrations add $Name
-
-if ($LASTEXITCODE -eq 0) {
- Write-Host "β Migratsiya muvaffaqiyatli yaratildi!" -ForegroundColor Green
-} else {
- Write-Error "β Migratsiya yaratishda xatolik yuz berdi."
-}
\ No newline at end of file
diff --git a/src/Sheetly.CLI/tools/init.ps1 b/src/Sheetly.CLI/tools/init.ps1
deleted file mode 100644
index 2d63d7e..0000000
--- a/src/Sheetly.CLI/tools/init.ps1
+++ /dev/null
@@ -1,3 +0,0 @@
-# Export functions when package is loaded in PMC
-Import-Module "$PSScriptRoot\Add-SheetlyMigration.ps1" -Force
-Set-Alias -Name add-sheetly-migration -Value Add-SheetlyMigration -Scope Global
\ No newline at end of file
diff --git a/src/Sheetly.Core/Migration/MigrationBuilder.cs b/src/Sheetly.Core/Migration/MigrationBuilder.cs
index 6b83c97..5e34d13 100644
--- a/src/Sheetly.Core/Migration/MigrationBuilder.cs
+++ b/src/Sheetly.Core/Migration/MigrationBuilder.cs
@@ -64,12 +64,6 @@ public static MigrationSnapshot BuildFromContext(Type contextType, ModelBuilder
MaxLength = prop.GetCustomAttribute()?.Length
};
- // Store custom attributes for legacy compatibility (though deprecated)
- var attrs = prop.GetCustomAttributes().Select(a => a.GetType().Name.Replace("Attribute", "")).ToList();
-#pragma warning disable CS0618 // Intentional use of deprecated property for backward compatibility
- if (attrs.Count != 0) column.Attributes = string.Join(", ", attrs.Select(a => $"[{a}]"));
-#pragma warning restore CS0618
-
if (prop.Name.EndsWith("Id", StringComparison.OrdinalIgnoreCase) && !column.IsPrimaryKey)
{
var relatedName = prop.Name.Substring(0, prop.Name.Length - 2);
diff --git a/src/Sheetly.Core/Migration/MigrationSnapshot.cs b/src/Sheetly.Core/Migration/MigrationSnapshot.cs
index 11c0fa2..fa2f548 100644
--- a/src/Sheetly.Core/Migration/MigrationSnapshot.cs
+++ b/src/Sheetly.Core/Migration/MigrationSnapshot.cs
@@ -64,18 +64,6 @@ public class ColumnSchema
// Additional metadata
public string? Comment { get; set; }
public string? Collation { get; set; }
-
- // Legacy support
- [Obsolete("Use specific constraint properties instead")]
- public string? Attributes { get; set; }
-
- // Deprecated property name - use ForeignKeyTable
- [Obsolete("Use ForeignKeyTable instead")]
- public string? RelatedTable
- {
- get => ForeignKeyTable;
- set => ForeignKeyTable = value;
- }
}
///
diff --git a/src/Sheetly.Core/Migrations/MigrationAttribute.cs b/src/Sheetly.Core/Migrations/MigrationAttribute.cs
index a5acb3a..2447f21 100644
--- a/src/Sheetly.Core/Migrations/MigrationAttribute.cs
+++ b/src/Sheetly.Core/Migrations/MigrationAttribute.cs
@@ -1,13 +1,8 @@
namespace Sheetly.Core.Migrations;
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
-public class MigrationAttribute : Attribute
+public class MigrationAttribute(string id) : Attribute
{
/// Format: yyyyMMddHHmmss_MigrationName
- public string Id { get; }
-
- public MigrationAttribute(string id)
- {
- Id = id ?? throw new ArgumentNullException(nameof(id));
- }
+ public string Id { get; } = id ?? throw new ArgumentNullException(nameof(id));
}
diff --git a/src/Sheetly.Core/Sheetly.Core.csproj b/src/Sheetly.Core/Sheetly.Core.csproj
index 44afc69..9d0af79 100644
--- a/src/Sheetly.Core/Sheetly.Core.csproj
+++ b/src/Sheetly.Core/Sheetly.Core.csproj
@@ -5,7 +5,7 @@
enableSheetly.Core
- 1.0.1
+ 1.0.2DotnetologMuqimjon MamadaliyevCopyright (c) 2025β2026 Muqimjon Mamadaliyev
@@ -23,7 +23,7 @@
-
+
diff --git a/src/Sheetly.Core/SheetsContext.cs b/src/Sheetly.Core/SheetsContext.cs
index 2790c96..d9ee563 100644
--- a/src/Sheetly.Core/SheetsContext.cs
+++ b/src/Sheetly.Core/SheetsContext.cs
@@ -132,7 +132,6 @@ private async Task> GetAppliedMigrationsFromRemoteAsync()
var rows = await Provider.GetAllRowsAsync(HistoryTable);
- // Skip header row (index 0), get MigrationId from first column
return rows.Skip(1)
.Where(r => r.Count > 0 && !string.IsNullOrEmpty(r[0]?.ToString()))
.Select(r => r[0]!.ToString()!)
diff --git a/src/Sheetly.Core/SheetsSet.cs b/src/Sheetly.Core/SheetsSet.cs
index 082831f..822758b 100644
--- a/src/Sheetly.Core/SheetsSet.cs
+++ b/src/Sheetly.Core/SheetsSet.cs
@@ -1,4 +1,4 @@
-ο»Ώusing Sheetly.Core.Abstractions;
+using Sheetly.Core.Abstractions;
using Sheetly.Core.Mapping;
using Sheetly.Core.Migration;
using System.Collections;
@@ -129,7 +129,6 @@ private async Task ProcessIncludes(List entities)
relatedSchema = allSchemas.Values.FirstOrDefault(s => s.ClassName == targetType.Name);
if (relatedSchema == null) continue;
}
- // Always use the schema's actual table name for provider calls
var actualTableName = relatedSchema.TableName;
if (!loadedTables.TryGetValue(actualTableName, out List