paint-brush
Entity Framework 8 - Trik pou klas pasyèl ou ta dwe konnenpa@markpelf
Nouvo istwa

Entity Framework 8 - Trik pou klas pasyèl ou ta dwe konnen

pa Mark Pelf17m2025/02/19
Read on Terminal Reader

Twò lontan; Pou li

Nan EF 8 - Database First apwòch klas EF ki te pwodwi yo pa ka pwolonje dirèkteman ak fonksyonalite adisyonèl. Pou simonte sa a, nou ka ogmante yon pati nan klas C#. Atik sa a prezante ke trik nouvèl itil pou pwolonje fonksyonalite nan yon anviwònman EF/ASP.NET.
featured image - Entity Framework 8 - Trik pou klas pasyèl ou ta dwe konnen
Mark Pelf HackerNoon profile picture

Atik sa a montre plizyè teknik pou itilize yon pati C# klas pou adrese pwoblèm komen nan EF 8/ASP.NET8.


Résumé: Nan EF 8 – Database First apwòch klas EF ki te pwodwi yo pa kapab pwolonje dirèkteman ak fonksyon adisyonèl paske yo ranplase yo lè modèl la rejenere. Pou simonte sa a, nou ka ogmante klas pasyèl C#. Atik sa a prezante ke trik nouvèl itil pou pwolonje fonksyonalite nan yon anviwònman EF/ASP.NET.

1 Entity Framework Core – Premye Apwòch baz done

Nan pwojè C#/ASP.NET 8 MVC mwen an, mwen itilize apwòch Entity Framework Core Database First . Sa nesesè paske plizyè aplikasyon atravè diferan teknoloji konte sou menm baz done SQL sèvè a. Pou jenere yon modèl nan baz done a, mwen itilize EFCorePowerTools.


Pwoblèm nan parèt lè modèl EF pwodwi a bezwen mete ajou pou reflete chanjman nan chema baz done a. Depi klas antite EF ki te pwodwi yo pral ranplase, nenpòt modifikasyon yo te fè yo pèdi. Sa a se yon pwoblèm paske, pafwa, nou bezwen pwolonje antite EF yo pou itilize nan aplikasyon an.


Pou rezoud pwoblèm sa a, mwen konte sou ke trik nouvèl ki enplike yon pati C# klas , ki pral eksplike anba a.

2 Yon Sitiyasyon tipik nan aplikasyon C#/EF/ASP.NET

Nan yon aplikasyon tipik C#/EF/ASP.NET 8 MVC, sitiyasyon an ta ka sanble ak kòd sa a:

 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //this is typical class generated by EF Core Power Tools //in EF-Database-First approach // <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated> [PrimaryKey("Id")] public partial class Customer { //Customer-partial-class-1 [Key] [StringLength(15)] public string? Id { get; set; } [StringLength(15)] public string? NAME { get; set; } public short? Language { get; set; } } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //this is typical model calls for ASP.NET MVC public class CustomerEdit_ViewModel { //model public string? Id { get; set; } = null; //view model // this is our Customer Entity from EF Core public Customer? Customer1 { get; set; } = null; //this is flag for submit button public bool IsSubmit { get; set; } = false; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //this is typical controller for ASP.NET MVC public class CustomersController : Controller { // some Controller code here public async Task<ActionResult> CustomerEdit(CustomerEdit_ViewModel model) { if (model.IsSubmit) { // Model validation is done during model binding // we have to check if model is valid if (ModelState.IsValid) { if (model.Customer1 != null) { //we update existing customer in database //redirect to the list of customers } } else { // we go for presentation of validation errors ModelState.AddModelError("", "PleaseCorrectAllErrors"); } } else { ModelState.Clear(); //go for presentation of original data if (model.Id != null) { //get Customer by Id from database } } return View("CustomerEdit", model); } }

Isit la, Kliyan-pasyèl-klas-1 se yon klas ki te pwodwi pa EF (via jeni ranvèse soti nan baz done a). Li gen ladann kèk atribi validation ki koresponn ak kontrent baz done. Anjeneral yo itilize klas sa a nan yon klas modèl (egzanp, CustomerEdit_ViewModel ), kote atribi validasyon yo trete pandan yon aksyon oswa yon metòd (egzanp, CustomerEdit ).

3 Trick 1 - Sèvi ak Klas Pasyèl pou ajoute Pwopriyete Custom

Si nou bezwen ajoute pwopriyete nan klas ki pwodwi a, nou pa ka modifye dirèkteman Customer-partial-class-1 , paske fè sa ta mennen nan chanjman yo te ranplase. Olye de sa, nou ka kreye Customer-partial-class-2 epi ajoute pwopriyete koutim nou yo la. Pou anpeche EF enkli pwopriyete sa yo nan modèl la, nou dwe itilize atribi [NotMapped] .


Men yon egzanp:

 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //this is typical class generated by EF Core Power Tools //in EF-Database-First approach // <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated> [PrimaryKey("Id")] public partial class Customer { //Customer-partial-class-1 [Key] [StringLength(15)] public string? Id { get; set; } [StringLength(15)] public string? NAME { get; set; } public short? Language { get; set; } } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //this is our partial class that extends our generated class //and is not overwritten by EF Core Power Tools //we use it to add some additional properties public partial class Customer { //Customer-partial-class-2 [NotMapped] public int NumberOfCreditCards { get; set; } = 0; [NotMapped] public string? LanguageString { get { string? result = "Unknown"; if (Language == 1) { result = "English"; } else if (Language == 2) { result = "German"; } return result; } } } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //this is typical model calls for ASP.NET MVC public class CustomerEdit_ViewModel { //model public string? Id { get; set; } = null; //view model // this is our Customer Entity from EF Core public Customer? Customer1 { get; set; } = null; //this is flag for submit button public bool IsSubmit { get; set; } = false; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //this is typical controller for ASP.NET MVC public class CustomersController : Controller { // some Controller code here //............. //this is typical action for editing customer public async Task<ActionResult> CustomerEdit(CustomerEdit_ViewModel model) { if (model.IsSubmit) { // Model validation is done during model binding // we have to check if model is valid if (ModelState.IsValid) { if (model.Customer1 != null) { //we update existing customer in database //redirect to the list of customers } } else { // we go for presentation of validation errors ModelState.AddModelError("", "PleaseCorrectAllErrors"); } } else { ModelState.Clear(); //go for presentation of original data if (model.Id != null) { //get Customer by Id from database } } return View("CustomerEdit", model); } }

Kòd la, ak kòmantè detaye, ta dwe pwòp tèt ou-eksplikasyon.

4 Trick 2 - Sèvi ak yon pati nan klas pou ajoute personnalisé Validation attributs

Pafwa, atribi validasyon otomatikman pwodwi nan EF yo pa ase, epi nou bezwen ajoute règ validasyon koutim. Ankò, klas pasyèl yo vin pote sekou. Anba a se yon egzanp:

 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //this is typical class generated by EF Core Power Tools //in EF-Database-First approach // <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated> [PrimaryKey("Id")] public partial class Customer { //Customer-partial-class-1 [Key] [StringLength(15)] public string? Id { get; set; } [StringLength(15)] public string? NAME { get; set; } public short? Language { get; set; } } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //this is our partial class that extends our generated class //and is not overwritten by EF Core Power Tools //we use it to add some additional properties //and do some additional validation [MetadataType(typeof(Customer_MetaData))] public partial class Customer { //Customer-partial-class-2 public Customer() { TypeDescriptor.AddProviderTransparent( new AssociatedMetadataTypeTypeDescriptionProvider( typeof(Customer), typeof(Customer_MetaData)), typeof(Customer)); } [NotMapped] public int NumberOfCreditCards { get; set; } = 0; [NotMapped] public string? LanguageString { get { string? result = "Unknown"; if (Language == 1) { result = "English"; } else if (Language == 2) { result = "German"; } return result; } } } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //this is our metadata class for our partial class //purpose of this class is to add validation attributes to our partial class //in addition to those that are already in generated class public class Customer_MetaData { //main trick here is that we are adding more validation attributes //in addition to those in generated class [Required] [MinLength(5)] public string? Id { get; set; } = string.Empty; //main trick here is that we are adding more validation attributes //in addition to those in generated class [Required] [MinLength(3)] public string? NAME { get; set; } = string.Empty; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //this is typical model calls for ASP.NET MVC public class CustomerEdit_ViewModel { //model public string? Id { get; set; } = null; //view model // this is our Customer Entity from EF Core public Customer? Customer1 { get; set; } = null; //this is flag for submit button public bool IsSubmit { get; set; } = false; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //this is utility class for validation public class ValidationUtil { /// <summary> /// Validates the specified model object against custom validation rules. /// </summary> /// <param name="model">The model object to validate.</param> /// <param name="modelState">The ModelStateDictionary to store validation errors.</param> /// <param name="logger">The logger to log errors.</param> /// <param name="prefix">An optional prefix for error keys in the ModelStateDictionary.</param> /// <returns>True if validation is successful; otherwise, false.</returns> /// <exception cref="ArgumentNullException">Thrown when the model is null.</exception> public static bool ValidateModelForCustomRules( object model, ModelStateDictionary modelState, ILogger? logger, string? prefix = null) { bool validationSuccessful = false; try { if (model == null) { throw new ArgumentNullException(nameof(model)); } else { var validationContext = new ValidationContext(model); var validationResults = new List<ValidationResult>(); Validator.TryValidateObject(model, validationContext, validationResults, true); foreach (var result in validationResults) { foreach (var memberName in result.MemberNames) { string key = string.IsNullOrEmpty(prefix) ? memberName : $"{prefix}.{memberName}"; modelState.AddModelError(key, result.ErrorMessage ?? "Error"); } } //Go recursively into depth for all properties of the model object that are objects themselves //we must go manually recursively into depth because API Validator.TryValidateObject does validation //only for class properties on first level foreach (var property in model.GetType().GetProperties()) { if (property.PropertyType.IsClass && property.PropertyType != typeof(string)) { var propertyValue = property.GetValue(model); if (propertyValue != null) { validationSuccessful &= ValidateModelForCustomRules(propertyValue, modelState, logger, property.Name); } } } } } catch (Exception ex) { string methodName = $"Type: {System.Reflection.MethodBase.GetCurrentMethod()?.DeclaringType?.FullName}, " + $"Method: ValidateModel; "; logger?.LogError(ex, methodName); validationSuccessful = false; } return validationSuccessful; } } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //this is typical controller for ASP.NET MVC public class CustomersController : Controller { // some Controller code here //............. //this is typical action for editing customer public async Task<ActionResult> CustomerEdit(CustomerEdit_ViewModel model) { if (model.IsSubmit) { // Model validation is done during model binding but we need more //validating for custom validation rules ValidationUtil.ValidateModelForCustomRules(model, ModelState, null); // we have to check if model is valid if (ModelState.IsValid) { if (model.Customer1 != null) { //we update existing customer in database //redirect to the list of customers } } else { // we go for presentation of validation errors ModelState.AddModelError("", "PleaseCorrectAllErrors"); } } else { ModelState.Clear(); //go for presentation of original data if (model.Id != null) { //get Customer by Id from database } } return View("CustomerEdit", model); } }

Kòm ou ka wè, nou modifye Customer-partial-class-2 epi ajoute yon klas Customer_MetaData . Objektif la isit la se ajoute validation adisyonèl pou pwopriyete a NON, ki egzije yon minimòm de 3 karaktè.


Nan ASP.NET MVC, nou ka itilize ModelState pou valide ak rekipere mesaj erè. Remake byen ke nou menm tou nou te oblije sèvi ak metòd sèvis piblik ValidationUtil.ValidateModelForCustomRules manyèlman deklanche validasyon koutim.


Kòd la ak kòmantè yo ta dwe bay tout detay ki nesesè pou konprann teknik sa a.

5 Konklizyon

Nan aplikasyon C#/EF/ASP.NET 8 MVC mwen an, mwen itilize teknik ki anwo yo ak klas C# pasyèl pou yon ekstansyon pou fonksyonalite klas EF pwodwi yo. Ke trik nouvèl sa yo senplifye senaryo komen yo, fè kòd la pi kout epi pi fasil pou kenbe.