{"id":20668694,"url":"https://github.com/n-yousefi/derafsh","last_synced_at":"2025-04-19T18:09:01.706Z","repository":{"id":133177356,"uuid":"122454220","full_name":"n-yousefi/Derafsh","owner":"n-yousefi","description":" Derafsh is an ORM based on the ViewModels","archived":false,"fork":false,"pushed_at":"2022-02-22T08:21:33.000Z","size":2171,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-29T11:22:53.324Z","etag":null,"topics":["ado-net","c-sharp","database","dotnet-core","dotnet-core2","entity-framework","orm","orm-aspnet-product","sql","sql-server","viewmodel-pattern"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/n-yousefi.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}},"created_at":"2018-02-22T09:03:25.000Z","updated_at":"2022-09-28T07:16:38.000Z","dependencies_parsed_at":null,"dependency_job_id":"ed67919a-ee3f-4028-a17f-f7dd5005d0d5","html_url":"https://github.com/n-yousefi/Derafsh","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/n-yousefi%2FDerafsh","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/n-yousefi%2FDerafsh/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/n-yousefi%2FDerafsh/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/n-yousefi%2FDerafsh/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/n-yousefi","download_url":"https://codeload.github.com/n-yousefi/Derafsh/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249758643,"owners_count":21321563,"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","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":["ado-net","c-sharp","database","dotnet-core","dotnet-core2","entity-framework","orm","orm-aspnet-product","sql","sql-server","viewmodel-pattern"],"created_at":"2024-11-16T20:10:54.620Z","updated_at":"2025-04-19T18:09:01.700Z","avatar_url":"https://github.com/n-yousefi.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"### This repo has been deprecated as it is legacy and is no longer maintained.\n\n# Derafsh O/RM\nDerafsh is an object-relational mapper that enables .NET developers to read or write operations in single statements. \nYou can easily read a complex object from (or write to) multiple related tables at SQL Server database.\n\nDefinitely, Derafsh does not satisfy all your needs, But it probably will remove a lot of repetitive tasks.\n## ViewModels Programming\nEverything that Derafsh does is based on the ViewModels (complex objects). You just need to prapare the prepare the ViewModel \nand then Derafsh will do the rest. Perhaps we can call it, ViewModels Programming or ViewModels O/RM. \n\n# An example\nWith the help of Derafsh, we can create one insert, edit or index form for all objects and complex objects. I've created a simple example to show the goal of creating Derafsh: \n* [Derafsh-Sample](https://github.com/n-yousefi/Derafsh-Sample)\n\n## Installing\nInstall as [NuGet package](https://www.nuget.org/packages/Derafsh/):\nPackage manager:\n```powershell\nInstall-Package Derafsh\n```\n.NET CLI:\n```bash\ndotnet add package Derafsh\n```\n## Getting Started\nI'm going to use these tables for my examples:\n![Example](https://github.com/n-yousefi/Derafsh/blob/master/diagram.png)\nThe Identity model:\n```c#\npublic class Identity\n{\n     [PrimaryKey]\n     public int Id {get; set;}\n     public int IdentityEnumId { get; set; } \n     [ForeignKey(\"Person\")]\n     public int? PersonId { get; set; }\n     [ForeignKey(\"Organization\")]\n     public int? OrganizationId { get; set; }\n     public bool IsActive {get; set;}\n     public bool IsDeleted {get; set;}\n}\n```\n### Preparing the ViewModel\nWith Derafsh you can easily read multiple related tables to a ViewModel List or write a ViewModel to its own tables.\nYou must create your own object and determine the relations between the tables. \n#### Join \nIf your model contains some foreign keys then you can use the Join attribute to specify that relation for Derafsh.\n(This means that you can use the Join attribute in One-to-One or Many-To-One relationships)\nIn the example if I create the ViewModel like this:\n```c#\n[Join]\npublic PersonViewModel Person { get; set; }\npublic OrganizationViewModel Organization { get; set; }\n```\nThen Derafsh will ignore the Organization but it will read/write the related Person by the Identity.\n#### InverseJoin\nIf you have One-to-Many relationships that means your table primary key is a foreign key in other tables, you can use the\nInverseJoin attribute.\nIn the example if I create the ViewModel as follow:\n```c#\n[InverseJoin]       \npublic List\u003cPhoneViewModel\u003e Phone { get; set; }\npublic List\u003cAddressViewModel\u003e Address { get; set; }\n```\nThen Derafsh will ignore the Address but it will read/write the list of Phones for the Identity.\n\nFull ViewModel for Identity:\n```c#\n[Table(\"Identity\")]\npublic class IdentityViewModel:Models.Identity\n{\n     private PersonViewModel _person;\n     private OrganizationViewModel _organization;\n     [Join]\n     public PersonViewModel Person\n     {\n         get =\u003e IdentityEnumId != (int) IdentityEnum.Person ? null : _person;\n         set =\u003e _person = value;\n     }\n     [Join]\n     public OrganizationViewModel Organization\n     {\n         get =\u003e IdentityEnumId != (int) IdentityEnum.Organization ? null : _organization;\n         set =\u003e _organization = value;\n     }\n     [InverseJoin]\n     public List\u003cPhoneViewModel\u003e Phone { get; set; }\n     [InverseJoin]\n     public List\u003cAddressViewModel\u003e Address { get; set; }\n}\n```\n### Insert a ViewModel to the database\n```c#\nTask\u003cint\u003e Insert\u003cT\u003e(object viewModel, CancellationToken cancellationToken=null, SqlTransaction transaction = null);\n```\nExample usage:\n```c#\nvar identity = new IdentityViewModel()\n{\n      IdentityEnumId =  (int) IdentityEnum.Person,\n      Person = new PersonViewModel()\n      {\n           FirstName = \"Naser\",\n           LastName = \"Yousefi\",\n           BirthCertificatedCityId = cityId,\n           ...\n      },\n      Address = new List\u003cAddressViewModel\u003e()\n      {\n            new AddressViewModel()\n            {\n                  FullAddress = \"Home: The earth\",\n                  //...\n            },\n            new AddressViewModel()\n            {\n                  FullAddress = \"Work: The oceans\",\n                  //...\n            },\n       },\n       Phone = new List\u003cAddressViewModel\u003e()\n       {\n            new PhoneViewModel()\n            {\n                 Number = \"+678 768 1217\",\n                 //...    \n            }\n       },\n       IsActive = true,\n       IsDeleted = false\n} \nvar result = await databaseActions.Insert\u003cIdentityViewModel\u003e(identity, cancellationToken, transaction);\n```\n### Fill an IEnumerable of ViewModels from the database\n```c#\nTask\u003cIEnumerable\u003cT\u003e\u003e Select\u003cT\u003e(QueryConditions queryConditions = null, FilterRequest filter = null, SqlTransaction transaction = null);\n```\n#### Query conditions\nYou can pass a QueryConditions object that contain your condition for each table. \nQueryConditions Methods:\n```c#\nvar conditions = new QueryConditions();\n// Adding a condition for spacefic table:\nconditions.AddCondition(\"TableName\", \"Condition\");\n// Adding a condition for all tables that have the mentioned ColumnName.\nconditions.AddPublicCondition(\"ColumnName\",\"Condition\");\n```\n#### Filtering the results\nYou can filter the results based on your preferments. \n```c#\npublic FilterRequest(int pageNumber, int pageSize, string sort, string sortDirection, string searchPhrase);\n```\nExample usage:\n```c#\nvar conditions = new QueryConditions();\nconditions.AddCondition(\"Identity\", \"id=10\");\nconditions.AddPublicCondition(\"IsActive\",\"IsActive=1\");\nconditions.AddPublicCondition(\"IsDeleted\", \"IsDeleted=0\");\n\nvar filter = new FilterRequest(1,20,\"Id\",\"Asc\",\"\");\nIEnumerable\u003cIdentityViewModel\u003e items = await databaseActions.Select\u003cIdentityViewModel\u003e(conditions, filter);\n```\n### Finding by id \n```c#\nTask\u003cT\u003e Find\u003cT\u003e(int id, QueryConditions queryConditions = null, SqlTransaction transaction = null);\n```\nExample usage:\n```c#\nvar conditions = new QueryConditions();\nconditions.AddPublicCondition(\"IsDeleted\", \"IsDeleted = 0\");\nvar model = await databaseActions.Find\u003cIdentityViewModel\u003e(1000,conditions,transaction);\n```\n### Showing an Abstract table of ViewModel\nUsually you need to display a list of your ViewModel to the users. You can use the Select method with filtering the results but\nloading all fields of ViewModels is costly. For this purpose, I've created an attribute and a method called Abstract.\n```c#\nTask\u003cDataTable\u003e Abstract\u003cT\u003e(string conditions = null, FilterRequest filterRequest = null, SqlTransaction transaction = null);\n```\nYou can use the Abstract attribute over the Join properties (Not over the InversJoins).\n**Note:** For now, you can only use this attribute only over the Table columns properties. \n\nIn the Example if I use Abstract attribute over the Person Join then the Person abstract properties will also be seen in the\nresult.\n```c#\n[Table(\"Identity\")]\npublic class IdentityViewModel:Models.Identity\n{\n     [Abstract]\n     [Join]\n     public PersonViewModel Person { get; set; }\n     [Abstract]\n     [Join]\n     public OrganizationViewModel Organization { get; set; }\n}\n[Table(\"Person\")]\npublic class PersonViewModel:Models.Person\n{\n     [Abstract]\n     [Display(Name = \"First Name\")]\n     public string FirstName { get; set; }\n     [Abstract]\n     [Display(Name = \"Last Name\")]\n     public string LastName { get; set; }\n}\n[Table(\"Organization\")]\npublic class OrganizationViewModel:Models.Organization\n{\n     [Abstract]\n     [Display(Name = \"Company\")]\n     public string Name { get; set; }\n     [Abstract]\n     [Display(Name = \"Registration Number\")]\n     public string RegistrationNumber { get; set; }\n}\n```\nExample usage:\n```c#\nvar filter = new FilterRequest(1, pageSize, \"Id\", \"Asc\", \"\");\nvar conditions = \"Date \u003e '2012-11-29 18:21:11.123' and Identity.IsActive = 1 and Identity.Isdeleted = 0\"\nvar items = await databaseActions.Abstract\u003cIdentityViewModel\u003e(conditions, filter);\n```\n|  First Name   |   Last Name   |   Company  | Registration Number |\n| ------------- | ------------- | ---------- | ------------------- |\n|     null      |      null     | Opt-xa Inc |     3242342352      |\n|     Javad     | Hajian-nezhad |    null    |        null         |\n|    Mohammad   |  Kheirandish  |    null    |        null         |\n|     null      |      null     | Desire Inc |     9873214654      |\n\n### Update a ViewModel in the database\nYou can pass a ViewModel to Update method and then all VewModel instances will be updated in database.\n**Note:** all instances in update method must have an Id property filled with valid value!\nTask\u003cint\u003e Update\u003cT\u003e(object viewModel,CancellationToken cancellationToken, SqlTransaction transaction = null);\n```c#\nvar identity = new IdentityViewModel()\n{\n      Id = 56\n      IdentityEnumId =  (int) IdentityEnum.Person,\n      Person = new PersonViewModel()\n      {\n           Id = 120\n           FirstName = \"Javad\",\n           LastName = \"Hajian-nezhad\",\n           BirthCertificatedCityId = cityId,\n           ...\n      },\n      Address = new List\u003cAddressViewModel\u003e()\n      {\n            new AddressViewModel()\n            {\n                  Id = 79\n                  FullAddress = \"Home: The galaxy\",\n                  //...\n            },\n            new AddressViewModel()\n            {\n                  Id = 12\n                  FullAddress = \"Work: The winds\",\n                  //...\n            },\n       },\n       Phone = new List\u003cAddressViewModel\u003e()\n       {\n            new PhoneViewModel()\n            {\n                 Id = 1520\n                 Number = \"+678 768 1217\",\n                 //...    \n            }\n       },\n       IsActive = true,\n       IsDeleted = false\n} \nvar result = await databaseActions.Update\u003cIdentityViewModel\u003e(identity, cancellationToken);\n```\n### Count\n```c#\nTask\u003cint\u003e Count\u003cT\u003e(string condition = \"\",CancellationToken cancellationToken=null, SqlTransaction transaction = null);\n```\nExample usage:\n```c#\nvar count = await databaseActions.Count\u003cIdentityViewModel\u003e(\"IsDeleted = 0\",cancellationToken, transaction);\n```\n### Soft delete \nDerafsh support soft deleting by setting \"IsDeleted\" property to true. It's very personalized now \nbut feel free to use Derafsh. I will add some options for selecting desired property. For now, you can use update method. \n```c#\nTask\u003cint\u003e UpdateByParentSoftDelete\u003cT\u003e(object viewModel, CancellationToken cancellationToken = null);\n```\n## Author\nNaser Yousefi\n     \n ## License\nLicensed under the Apache License, Version 2.0.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fn-yousefi%2Fderafsh","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fn-yousefi%2Fderafsh","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fn-yousefi%2Fderafsh/lists"}