{"id":32664278,"url":"https://github.com/chizaruu/datalayergenerator","last_synced_at":"2026-05-15T18:05:01.514Z","repository":{"id":320737062,"uuid":"1083178279","full_name":"Chizaruu/DataLayerGenerator","owner":"Chizaruu","description":"Visual Studio extension that auto-generates Entity Framework Core data access layers with CRUD operations from C# model classes","archived":false,"fork":false,"pushed_at":"2025-10-25T14:59:14.000Z","size":111,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-25T16:20:50.153Z","etag":null,"topics":["async-await","code-generation","code-generator","crud","csharp","data-layer","dependency-injection","dotnet","ef-core","entity-framework-core","net-framework","repository-pattern","roslyn","visual-studio","visual-studio-extension"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Chizaruu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-25T13:57:01.000Z","updated_at":"2025-10-25T14:58:43.000Z","dependencies_parsed_at":"2025-10-25T16:21:28.078Z","dependency_job_id":"28277b37-44df-4305-bae7-0486bb4113b0","html_url":"https://github.com/Chizaruu/DataLayerGenerator","commit_stats":null,"previous_names":["chizaruu/datalayergenerator"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/Chizaruu/DataLayerGenerator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Chizaruu%2FDataLayerGenerator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Chizaruu%2FDataLayerGenerator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Chizaruu%2FDataLayerGenerator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Chizaruu%2FDataLayerGenerator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Chizaruu","download_url":"https://codeload.github.com/Chizaruu/DataLayerGenerator/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Chizaruu%2FDataLayerGenerator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":282070789,"owners_count":26608933,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-31T02:00:07.401Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async-await","code-generation","code-generator","crud","csharp","data-layer","dependency-injection","dotnet","ef-core","entity-framework-core","net-framework","repository-pattern","roslyn","visual-studio","visual-studio-extension"],"created_at":"2025-10-31T23:01:34.202Z","updated_at":"2025-10-31T23:03:31.982Z","avatar_url":"https://github.com/Chizaruu.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"﻿# Data Layer Generator\n\nA Visual Studio 2022 extension that automatically generates Entity Framework data access layer classes from C# model classes with full CRUD operations, interfaces, and customizable options.\n\n## Features\n\n✨ **Right-click to generate** - Works directly from Solution Explorer context menu  \n✨ **Interactive CRUD selection** - Choose which operations to generate (GetAll, GetById, Add, Update, Delete)  \n✨ **Interface generation** - Automatically creates interfaces for dependency injection  \n✨ **Primary constructor support** - Uses modern C# 12 syntax for cleaner code  \n✨ **Smart model detection** - Analyzes classes and records with automatic ID property detection  \n✨ **Batch processing** - Generate data layers for multiple model files at once  \n✨ **Record support** - Works with both classes and records (including primary constructors)  \n✨ **Async-first** - Generates async methods with CancellationToken support  \n✨ **AsNoTracking optimization** - Uses read-only queries for better performance  \n✨ **XML documentation** - Generates comprehensive XML comments for all methods  \n✨ **Overwrite protection** - Prompts before replacing existing files  \n✨ **Detailed logging** - Progress tracking in Output Window  \n✨ **Customizable options** - Configure behavior through Tools → Options  \n✨ **Navigation properties** - Detects and handles EF navigation properties  \n✨ **Flexible structure** - Configurable folder structure and naming conventions\n\n## Requirements\n\n-   Visual Studio 2022 (Community, Professional, or Enterprise)\n-   .NET Framework 4.8\n-   Entity Framework Core (in your target project)\n\n## Installation\n\n### Option 1: Build from Source\n\n1. Install the **Visual Studio extension development** workload via Visual Studio Installer\n2. Clone or download this repository\n3. Open `DataLayerGenerator.sln` in Visual Studio 2022\n4. Build the solution (Ctrl+Shift+B)\n5. Close all Visual Studio instances\n6. Run the generated `.vsix` file from `bin/Debug/` or `bin/Release/`\n7. Restart Visual Studio\n\n### Option 2: From VSIX Package\n\n1. Download the `.vsix` file\n2. Close all Visual Studio instances\n3. Double-click the `.vsix` file\n4. Follow the installation wizard\n5. Restart Visual Studio\n\n## Configuration\n\nAccess settings through **Tools → Options → Data Layer Generator → General**\n\n### General Settings\n\n| Setting                  | Default                | Description                                |\n| ------------------------ | ---------------------- | ------------------------------------------ |\n| Data Layer Folder Name   | `Data`                 | Folder for generated data layer files      |\n| Data Layer Suffix        | `Data`                 | Suffix for data layer class names          |\n| Namespace Suffix         | `.Data`                | Appended to model namespace                |\n| DbContext Name           | `ApplicationDbContext` | Name of your DbContext class               |\n| Generate Interfaces      | `true`                 | Generate interfaces for data layer classes |\n| Create Interfaces Folder | `true`                 | Create separate 'Interfaces' subfolder     |\n\n### CRUD Methods\n\n| Setting                 | Default | Description                         |\n| ----------------------- | ------- | ----------------------------------- |\n| Generate GetAll Method  | `true`  | Generate GetAll() and GetAllAsync() |\n| Generate GetById Method | `true`  | Generate GetByIdAsync()             |\n| Generate Add Method     | `true`  | Generate AddAsync()                 |\n| Generate Update Method  | `true`  | Generate UpdateAsync()              |\n| Generate Delete Method  | `true`  | Generate DeleteAsync()              |\n\n### Advanced Settings\n\n| Setting                          | Default | Description                                  |\n| -------------------------------- | ------- | -------------------------------------------- |\n| Use Primary Constructor          | `true`  | Use C# 12 primary constructor syntax         |\n| Include Custom Query Placeholder | `false` | Add commented placeholder for custom queries |\n| Use AsNoTracking                 | `true`  | Use AsNoTracking() for read-only queries     |\n| Add XML Documentation            | `true`  | Add XML documentation comments to methods    |\n\n## Usage\n\n### Quick Start\n\n1. Create your model classes in a `Models` folder:\n\n```csharp\nnamespace MyProject.Models\n{\n    public class Product\n    {\n        public int Id { get; set; }\n        public string Name { get; set; }\n        public decimal Price { get; set; }\n        public int CategoryId { get; set; }\n\n        // Navigation property\n        public Category Category { get; set; }\n    }\n}\n```\n\n2. Right-click the model file in Solution Explorer\n3. Select **Generate Data Layer**\n4. Select which CRUD operations to include\n5. Click **Generate**\n\nThe extension creates:\n\n-   `Data/ProductData.cs` - Data access implementation\n-   `Data/Interfaces/IProductData.cs` - Interface (if enabled)\n\n### Generated Output\n\n**ProductData.cs:**\n\n```csharp\nusing Microsoft.EntityFrameworkCore;\nusing MyProject.Models;\nusing MyProject.Data.Interfaces;\n\nnamespace MyProject.Data;\n\n/// \u003csummary\u003e\n/// Data access layer for Product entities\n/// \u003c/summary\u003e\npublic class ProductData(ApplicationDbContext context) : IProductData\n{\n    /// \u003csummary\u003e\n    /// Gets all Product entities\n    /// \u003c/summary\u003e\n    public IReadOnlyList\u003cProduct\u003e GetAllProducts()\n    {\n        return [.. context.Products\n            .AsNoTracking()\n            .OrderBy(x =\u003e x.Id)];\n    }\n\n    /// \u003csummary\u003e\n    /// Gets all Product entities asynchronously\n    /// \u003c/summary\u003e\n    public async Task\u003cIReadOnlyList\u003cProduct\u003e\u003e GetAllProductsAsync(CancellationToken cancellationToken = default)\n    {\n        return await context.Products\n            .AsNoTracking()\n            .OrderBy(x =\u003e x.Id)\n            .ToListAsync(cancellationToken);\n    }\n\n    /// \u003csummary\u003e\n    /// Gets a Product entity by ID\n    /// \u003c/summary\u003e\n    public async Task\u003cProduct?\u003e GetProductByIdAsync(int id, CancellationToken cancellationToken = default)\n    {\n        return await context.Products\n            .AsNoTracking()\n            .FirstOrDefaultAsync(x =\u003e x.Id == id, cancellationToken);\n    }\n\n    /// \u003csummary\u003e\n    /// Adds a new Product entity\n    /// \u003c/summary\u003e\n    public async Task AddProductAsync(Product entity, CancellationToken cancellationToken = default)\n    {\n        await context.Products.AddAsync(entity, cancellationToken);\n        await context.SaveChangesAsync(cancellationToken);\n    }\n\n    /// \u003csummary\u003e\n    /// Updates an existing Product entity\n    /// \u003c/summary\u003e\n    public async Task UpdateProductAsync(Product entity, CancellationToken cancellationToken = default)\n    {\n        context.Products.Update(entity);\n        await context.SaveChangesAsync(cancellationToken);\n    }\n\n    /// \u003csummary\u003e\n    /// Deletes a Product entity by ID\n    /// \u003c/summary\u003e\n    public async Task DeleteProductAsync(int id, CancellationToken cancellationToken = default)\n    {\n        var entity = await context.Products.FindAsync([id], cancellationToken);\n        if (entity != null)\n        {\n            context.Products.Remove(entity);\n            await context.SaveChangesAsync(cancellationToken);\n        }\n    }\n}\n```\n\n**IProductData.cs:**\n\n```csharp\nusing MyProject.Models;\n\nnamespace MyProject.Data.Interfaces;\n\n/// \u003csummary\u003e\n/// Data access interface for Product entities\n/// \u003c/summary\u003e\npublic interface IProductData\n{\n    IReadOnlyList\u003cProduct\u003e GetAllProducts();\n    Task\u003cIReadOnlyList\u003cProduct\u003e\u003e GetAllProductsAsync(CancellationToken cancellationToken = default);\n    Task\u003cProduct?\u003e GetProductByIdAsync(int id, CancellationToken cancellationToken = default);\n    Task AddProductAsync(Product entity, CancellationToken cancellationToken = default);\n    Task UpdateProductAsync(Product entity, CancellationToken cancellationToken = default);\n    Task DeleteProductAsync(int id, CancellationToken cancellationToken = default);\n}\n```\n\n### CRUD Method Selection Dialog\n\nWhen generating, you can choose which methods to include:\n\n-   ☑️ **GetAll() / GetAllAsync()** - Retrieve all entities\n-   ☑️ **GetByIdAsync()** - Retrieve entity by ID\n-   ☑️ **AddAsync()** - Add new entity\n-   ☑️ **UpdateAsync()** - Update existing entity\n-   ☑️ **DeleteAsync()** - Delete entity by ID\n-   ☐ **Include placeholder for custom queries**\n\nQuick actions:\n\n-   **Select All** - Enable all CRUD operations\n-   **Deselect All** - Disable all operations\n\n### View Progress\n\n1. Open Output Window (View → Output or Ctrl+Alt+O)\n2. Select **Data Layer Generator** from the dropdown\n3. View detailed logs:\n    - Files being processed\n    - Models detected\n    - Files generated\n    - Any errors or warnings\n\nExample output:\n\n```\n[14:23:45] === Data Layer Generator v1.0.0 ===\n[14:23:45] Starting data layer generation...\n[14:23:45] Options: Folder=Data, Suffix=Data\n[14:23:45]   DbContext=ApplicationDbContext, GenerateInterfaces=True\n[14:23:45] Processing 1 file(s)...\n[14:23:45] Analyzing: Product.cs\n[14:23:45]   Found model: Product\n[14:23:45]   Created folder: Data\n[14:23:45]   Generated: ProductData.cs\n[14:23:46]   Generated interface: IProductData.cs\n[14:23:46]   Added to project: ProductData.cs\n[14:23:46]   Added to project: IProductData.cs\n[14:23:46] === Generation Complete ===\n[14:23:46] Data layer generation complete! Succeeded: 1 Failed: 0 Skipped: 0\n```\n\n## Examples\n\n### Record Types\n\n**Input:**\n\n```csharp\nnamespace MyProject.Models\n{\n    public record Customer(int Id, string Name, string Email);\n}\n```\n\n**Output:** Generates full CRUD data layer and interface for the `Customer` record.\n\n### Models Without ID Property\n\nIf a model doesn't have an `Id` or `{ClassName}Id` property:\n\n```csharp\npublic class Configuration\n{\n    public string Key { get; set; }\n    public string Value { get; set; }\n}\n```\n\nThe generator will:\n\n-   ✅ Generate GetAll methods\n-   ✅ Generate Add method\n-   ✅ Generate Update method\n-   ❌ Skip GetById method (no ID property)\n-   ❌ Skip Delete method (no ID property)\n\n### Custom ID Names\n\nThe generator recognizes both patterns:\n\n```csharp\npublic class Employee\n{\n    public int EmployeeId { get; set; }  // Recognized as ID\n    // ...\n}\n```\n\n### Models with Navigation Properties\n\n```csharp\npublic class Order\n{\n    public int Id { get; set; }\n    public int CustomerId { get; set; }\n    public DateTime OrderDate { get; set; }\n\n    // Navigation properties are detected but not included in method signatures\n    public Customer Customer { get; set; }\n    public ICollection\u003cOrderItem\u003e OrderItems { get; set; }\n}\n```\n\nGenerated methods use the entity type directly and let EF handle navigation properties.\n\n### Batch Processing Multiple Files\n\n1. Select multiple model files in Solution Explorer (Ctrl+Click)\n2. Right-click → **Generate Data Layer**\n3. Each file shows its own dialog for method selection\n4. All data layers are generated in one operation\n\n## Dependency Injection Setup\n\nAfter generating your data layers, register them in your DI container:\n\n```csharp\n// Program.cs or Startup.cs\nservices.AddDbContext\u003cApplicationDbContext\u003e(options =\u003e\n    options.UseSqlServer(connectionString));\n\n// Register data layers\nservices.AddScoped\u003cIProductData, ProductData\u003e();\nservices.AddScoped\u003cICustomerData, CustomerData\u003e();\nservices.AddScoped\u003cIOrderData, OrderData\u003e();\n```\n\nThen inject and use:\n\n```csharp\npublic class ProductService\n{\n    private readonly IProductData _productData;\n\n    public ProductService(IProductData productData)\n    {\n        _productData = productData;\n    }\n\n    public async Task\u003cIReadOnlyList\u003cProduct\u003e\u003e GetAllProductsAsync()\n    {\n        return await _productData.GetAllProductsAsync();\n    }\n}\n```\n\n## Troubleshooting\n\n### Extension doesn't appear in context menu\n\n-   Verify you're right-clicking `.cs` files in Solution Explorer\n-   Check Extensions → Manage Extensions to confirm it's installed and enabled\n-   Ensure the file is part of a project (not a loose file)\n-   Restart Visual Studio\n\n### Build errors in test project\n\n-   Change test project target framework from `net8.0-windows` to `net48`\n-   Visual Studio SDK packages only support .NET Framework\n-   See the updated test project file in the solution\n\n### No models found\n\n-   Ensure the class/record is `public`\n-   Verify the file contains valid C# syntax\n-   Check Output Window for detailed analysis logs\n-   Model must have at least one public property\n\n### Files not added to project\n\n-   Check Output Window for warnings about project addition\n-   Manually add files from the `Data` folder if needed\n-   Ensure the project file is not read-only\n\n### Options not taking effect\n\n-   Changes take effect immediately for new generations\n-   Previously generated files are not automatically updated\n-   Regenerate files to apply new options\n\n### DbContext mismatch\n\n-   Update **DbContext Name** in Tools → Options to match your context class\n-   Regenerate data layers after changing the DbContext name\n-   Ensure your DbContext has DbSet properties matching your model names (e.g., `DbSet\u003cProduct\u003e Products`)\n\n## Project Structure\n\n```\nDataLayerGenerator.Extension/\n├── Commands/\n│   └── GenerateDataLayerCommand.cs     # Command handler and orchestration\n├── Services/\n│   └── DataLayerGeneratorService.cs    # Roslyn-based code generation\n├── Options/\n│   └── GeneralOptionsPage.cs           # Settings/configuration page\n├── UI/\n│   ├── GenerateDataLayerDialog.xaml    # CRUD method selection dialog\n│   ├── GenerateDataLayerDialog.xaml.cs\n│   ├── OverwriteDialog.xaml            # File overwrite confirmation\n│   ├── OverwriteDialog.xaml.cs\n│   ├── PreviewDialog.xaml              # Code preview dialog\n│   ├── PreviewDialog.xaml.cs\n│   └── MemberSelectionItem.cs          # View model for UI items\n├── Constants.cs                         # Configuration constants\n├── DataLayerGeneratorPackage.cs        # VS Package entry point\n└── DataLayerGeneratorPackage.vsct      # Command definitions\n\nDataLayerGenerator.Tests/\n├── Performance/\n│   └── PerformanceTests.cs             # Performance benchmarks\n└── Helpers/\n    └── TestHelpers.cs                  # Test utilities and samples\n```\n\n## Development\n\n### Building the Extension\n\n1. Open `DataLayerGenerator.sln` in Visual Studio 2022\n2. Ensure all NuGet packages are restored\n3. Build the solution (Ctrl+Shift+B)\n4. The VSIX file will be in `bin/Debug/` or `bin/Release/`\n\n### Debugging\n\n1. Press **F5** to launch experimental instance\n2. Open a test project with model classes\n3. Test the extension\n4. Set breakpoints in the extension code\n5. Check Output Window → \"Data Layer Generator\" for logs\n\n### Running Tests\n\nThe solution includes comprehensive tests:\n\n```bash\n# Run all tests\ndotnet test\n\n# Run specific test category\ndotnet test --filter \"FullyQualifiedName~Performance\"\n```\n\n**Note:** Test project targets .NET Framework 4.8 (not .NET 8) because Visual Studio SDK packages require .NET Framework.\n\n### Key Technologies\n\n-   **Roslyn (Microsoft.CodeAnalysis.CSharp)** - C# syntax parsing and code generation\n-   **Visual Studio SDK 17.x** - IDE integration and extensibility\n-   **WPF** - User interface dialogs\n-   **VSIX** - Extension packaging and deployment\n-   **xUnit + FluentAssertions** - Unit testing\n\n## Performance\n\nThe generator is optimized for speed:\n\n-   Simple models: \u003c 1 second\n-   Large models (100+ properties): \u003c 2 seconds\n-   50 files batch: \u003c 20 seconds\n-   Concurrent processing supported\n-   Memory efficient (\u003c 50 MB growth over 100 iterations)\n\nPerformance tests are included in the solution to ensure regression-free development.\n\n## Known Limitations\n\n-   Only processes public classes and records (not internal, protected, or private)\n-   Nested classes are not supported\n-   Assumes Entity Framework Core conventions (DbSet properties named as plural)\n-   Primary key must be named `Id` or `{ClassName}Id`\n-   Generated code assumes standard EF Core patterns\n\n## Roadmap\n\nFuture enhancements under consideration:\n\n-   [ ] Support for composite primary keys\n-   [ ] Custom query template system\n-   [ ] Support for repository pattern generation\n-   [ ] Unit of Work pattern support\n-   [ ] Specification pattern support\n-   [ ] Support for Dapper or other ORMs\n-   [ ] Bulk operation methods (AddRange, DeleteRange)\n-   [ ] Search/filter method generation\n-   [ ] Pagination support\n-   [ ] Include/ThenInclude for navigation properties\n-   [ ] Integration with EF migrations\n\n## License\n\nMIT License\n\nCopyright (c) 2025 Developer Chizaruu\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n## Contributing\n\nContributions welcome! Areas for improvement:\n\n-   Additional CRUD patterns (Repository, Unit of Work)\n-   Support for other data access patterns\n-   Custom method templates\n-   Integration with other ORMs\n-   Performance optimizations\n-   Additional test coverage\n\n## Support\n\nFor issues or questions:\n\n1. Check the **Output Window** (View → Output → \"Data Layer Generator\") for detailed error messages\n2. Review the **Troubleshooting** section above\n3. Check **Tools → Options → Data Layer Generator** for configuration options\n4. Verify Visual Studio 2022 and .NET Framework 4.8 compatibility\n5. Create an issue with:\n    - Visual Studio version\n    - Extension version\n    - Steps to reproduce\n    - Output Window logs\n    - Sample model code\n    - Current option settings\n\n---\n\n**Made with ❤️ for Entity Framework developers**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchizaruu%2Fdatalayergenerator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchizaruu%2Fdatalayergenerator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchizaruu%2Fdatalayergenerator/lists"}