Windows应用中替代ASP.Net MVC TryUpdateModel()的方案咨询
Great question! TryUpdateModel is super handy in MVC for binding user input to entities, but since you're working in a Windows app without the System.Web.Mvc library, let's break down the best alternatives—starting with built-in EF features, then moving to more flexible options.
1. EF's Built-in Entry().CurrentValues.SetValues()
This is the closest out-of-the-box replacement for TryUpdateModel in Entity Framework. It automatically maps properties from your input object (like a Windows Forms model or DTO) to your tracked database entity, matching same-named, compatible-type properties and ignoring any that don't exist on the target.
Here's how to use it:
// Fetch the existing entity from your database (must be tracked by the context) var existingEntity = dbContext.YourEntities.Find(entityId); // Get your input model from the UI (e.g., a form's view model) var userInputModel = GetInputFromWindowsForm(); // Auto-map matching properties to the existing entity dbContext.Entry(existingEntity).CurrentValues.SetValues(userInputModel); // Save the changes to the database dbContext.SaveChanges();
Pro tip: Make sure the existing entity is tracked by your DbContext (using methods like Find, FirstOrDefault, or Attach if you're working with a detached entity).
2. Use Object Mapping Libraries (Like AutoMapper)
If you need more control over property mapping—for example, different property names, type conversions, or excluding sensitive properties—libraries like AutoMapper are perfect. They let you define reusable mapping rules and handle complex scenarios easily.
First, configure your mapping (do this once, like at app startup):
var mapperConfig = new MapperConfiguration(cfg => { cfg.CreateMap<YourInputModel, YourEntity>() .ForMember(dest => dest.Id, opt => opt.Ignore()) // Skip the primary key to avoid overwriting .ForMember(dest => dest.CreatedDate, opt => opt.Ignore()); // Ignore read-only audit fields }); IMapper mapper = mapperConfig.CreateMapper();
Then apply the mapping to your entity:
var existingEntity = dbContext.YourEntities.Find(entityId); var userInputModel = GetInputFromWindowsForm(); // Map input values to the existing tracked entity mapper.Map(userInputModel, existingEntity); dbContext.SaveChanges();
3. Roll Your Own Reflection-Based Method
If you don't want to add a third-party library, you can create a simple helper method using reflection to copy properties manually. This is lightweight and works for basic scenarios.
Here's a sample implementation:
public static void UpdateEntityFromModel<TEntity, TModel>(TEntity targetEntity, TModel sourceModel) where TEntity : class where TModel : class { var targetProps = typeof(TEntity).GetProperties(BindingFlags.Public | BindingFlags.Instance); var sourceProps = typeof(TModel).GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (var targetProp in targetProps) { // Find a matching property in the source by name and compatible type var sourceProp = sourceProps.FirstOrDefault(p => p.Name.Equals(targetProp.Name, StringComparison.OrdinalIgnoreCase) && targetProp.PropertyType.IsAssignableFrom(p.PropertyType)); if (sourceProp != null && targetProp.CanWrite) { var value = sourceProp.GetValue(sourceModel); targetProp.SetValue(targetEntity, value); } } }
Use it like this:
var existingEntity = dbContext.YourEntities.Find(entityId); var userInputModel = GetInputFromWindowsForm(); UpdateEntityFromModel(existingEntity, userInputModel); dbContext.SaveChanges();
Note: You'll want to add error handling (like null checks) and adjust for edge cases (e.g., value types vs reference types) if you use this in production.
Key Considerations
- Protect Sensitive Properties: No matter which method you use, always exclude sensitive fields (like passwords, permission levels) from being updated automatically. Use
Ignore()rules (in AutoMapper) or skip them in your reflection logic. - Tracked Entities: Ensure your target entity is tracked by the DbContext before applying updates—otherwise, EF won't detect the changes to save.
内容的提问来源于stack exchange,提问作者Farshad Nasehi

