Cas d'utilisation
/
Maintenance du code
Moderniser le code existant
modèle
•
Claude 3.7 Sonnet
Modernisez une application de bureau d'inventaire VB6 vers C# .NET 8 avec WPF : fournissez un plan de migration et un exemple de code réécrit pour un formulaire.
Migration de l'application d'inventaire VB6 vers C# .NET 8 avec WPF
Plan de migration
Phase 1 : Évaluation et planification
- Inventaire des fonctionnalités existantes
- Documentez tous les formulaires, modules et classes
- Identifier les connexions aux bases de données et les méthodes d'accès aux données
- Mappez la logique métier et les flux de travail
- Identifier les dépendances avec des tiers
- Planification de l'architecture
- Concevez une nouvelle structure de solution à l'aide du modèle MVVM
- Planifiez une stratégie de migration de base de données
- Définir la pile technologique (EF Core, etc.)
- Identifier les composants réutilisables
Phase 2 : Configuration de l'environnement
- Environnement de développement
- Configurer Visual Studio 2022
- Créez une nouvelle solution WPF avec .NET 8
- Configuration du contrôle de la source
- Configurer le pipeline CI/CD
- Création d'une structure de projet
- Création de projets principaux (modèles, ViewModels, Services)
- Configurer l'injection de dépendances
- Configuration de la journalisation et de la gestion des erreurs
Phase 3 : Migration des bases de données
- Évaluation des bases de données
- Analyser le schéma de base de données existant
- Planifiez la migration vers une base de données moderne si nécessaire
- Modèles principaux du Design Entity Framework
- implémentation de la couche d'accès aux données
- Création de configurations DbContext et d'entité
- Implémenter des référentiels
- Création de scripts de migration de données
Phase 4 : Migration de l'interface utilisateur
- Conception de l'interface utilisateur
- Création de styles et de thèmes WPF
- Concevez des commandes réutilisables
- Implémenter l'infrastructure MVVM de base
- Migration de formulaires
- Classer les formulaires par ordre de complexité/importance
- Implémenter un formulaire à la fois
- Créez des tests unitaires pour chaque formulaire
Phase 5 : Migration vers la logique métier
- Mise en œuvre de la couche service
- Migrer la logique métier vers les classes de services
- Mettre en œuvre des règles de validation
- Création de tests unitaires
- Intégration
- Connecter l'interface utilisateur aux services
- Mettre en œuvre la gestion des erreurs
- Ajouter une journalisation
Phase 6 : Test et déploiement
- Tests
- Tests unitaires
- Tests d'intégration
- Tests d'acceptation par les utilisateurs
- Déploiement
- Créer un programme d'installation
- Processus de déploiement des documents
- Stratégie de déploiement du plan
Exemple de migration : formulaire d'article d'inventaire
Formulaire VB6 original (supposé)
1' frmInventoryItem.frm
2Option Explicit
3
4Private Sub Form_Load()
5 ' Initialize form
6 txtItemID.Text = ""
7 txtName.Text = ""
8 txtDescription.Text = ""
9 txtQuantity.Text = "0"
10 txtPrice.Text = "0.00"
11 cboCategory.Clear
12
13 ' Load categories
14 Dim rs As ADODB.Recordset
15 Set rs = New ADODB.Recordset
16 rs.Open "SELECT CategoryID, CategoryName FROM Categories", conn, adOpenStatic
17
18 Do Until rs.EOF
19 cboCategory.AddItem rs!CategoryName
20 cboCategory.ItemData(cboCategory.NewIndex) = rs!CategoryID
21 rs.MoveNext
22 Loop
23 rs.Close
24End Sub
25
26Private Sub btnSave_Click()
27 ' Validate input
28 If Trim(txtName.Text) = "" Then
29 MsgBox "Please enter item name", vbExclamation
30 txtName.SetFocus
31 Exit Sub
32 End If
33
34 If Not IsNumeric(txtQuantity.Text) Then
35 MsgBox "Quantity must be numeric", vbExclamation
36 txtQuantity.SetFocus
37 Exit Sub
38 End If
39
40 If Not IsNumeric(txtPrice.Text) Then
41 MsgBox "Price must be numeric", vbExclamation
42 txtPrice.SetFocus
43 Exit Sub
44 End If
45
46 ' Save to database
47 Dim sql As String
48 If Trim(txtItemID.Text) = "" Then
49 ' Insert new record
50 sql = "INSERT INTO Inventory (Name, Description, CategoryID, Quantity, Price) VALUES ('" & _
51 Replace(txtName.Text, "'", "''") & "', '" & _
52 Replace(txtDescription.Text, "'", "''") & "', " & _
53 cboCategory.ItemData(cboCategory.ListIndex) & ", " & _
54 Val(txtQuantity.Text) & ", " & _
55 Val(txtPrice.Text) & ")"
56 conn.Execute sql
57 MsgBox "Item added successfully", vbInformation
58 Else
59 ' Update existing record
60 sql = "UPDATE Inventory SET Name = '" & Replace(txtName.Text, "'", "''") & _
61 "', Description = '" & Replace(txtDescription.Text, "'", "''") & _
62 "', CategoryID = " & cboCategory.ItemData(cboCategory.ListIndex) & _
63 ", Quantity = " & Val(txtQuantity.Text) & _
64 ", Price = " & Val(txtPrice.Text) & _
65 " WHERE ItemID = " & Val(txtItemID.Text)
66 conn.Execute sql
67 MsgBox "Item updated successfully", vbInformation
68 End If
69
70 Unload Me
71End Sub
72
73Private Sub btnCancel_Click()
74 Unload Me
75End SubMigration de fichiers WPF vers C# .NET 8
1. Modèles
1// Models/InventoryItem.cs
2namespace InventoryApp.Models
3{
4 public class InventoryItem
5 {
6 public int ItemId { get; set; }
7 public string Name { get; set; } = string.Empty;
8 public string Description { get; set; } = string.Empty;
9 public int CategoryId { get; set; }
10 public string CategoryName { get; set; } = string.Empty;
11 public int Quantity { get; set; }
12 public decimal Price { get; set; }
13 }
14
15 public class Category
16 {
17 public int CategoryId { get; set; }
18 public string CategoryName { get; set; } = string.Empty;
19 }
20}2. Accès aux données
1// Data/AppDbContext.cs
2using InventoryApp.Models;
3using Microsoft.EntityFrameworkCore;
4
5namespace InventoryApp.Data
6{
7 public class AppDbContext : DbContext
8 {
9 public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
10
11 public DbSet<InventoryItem> InventoryItems { get; set; }
12 public DbSet<Category> Categories { get; set; }
13
14 protected override void OnModelCreating(ModelBuilder modelBuilder)
15 {
16 modelBuilder.Entity<InventoryItem>().ToTable("Inventory");
17 modelBuilder.Entity<Category>().ToTable("Categories");
18 }
19 }
20}3. Des services
1// Services/IInventoryService.cs
2using InventoryApp.Models;
3using System.Collections.Generic;
4using System.Threading.Tasks;
5
6namespace InventoryApp.Services
7{
8 public interface IInventoryService
9 {
10 Task<List<Category>> GetCategoriesAsync();
11 Task<InventoryItem?> GetInventoryItemAsync(int id);
12 Task<bool> SaveInventoryItemAsync(InventoryItem item);
13 }
14}
15
16// Services/InventoryService.cs
17using InventoryApp.Data;
18using InventoryApp.Models;
19using Microsoft.EntityFrameworkCore;
20using System.Collections.Generic;
21using System.Threading.Tasks;
22
23namespace InventoryApp.Services
24{
25 public class InventoryService : IInventoryService
26 {
27 private readonly AppDbContext _dbContext;
28
29 public InventoryService(AppDbContext dbContext)
30 {
31 _dbContext = dbContext;
32 }
33
34 public async Task<List<Category>> GetCategoriesAsync()
35 {
36 return await _dbContext.Categories.ToListAsync();
37 }
38
39 public async Task<InventoryItem?> GetInventoryItemAsync(int id)
40 {
41 return await _dbContext.InventoryItems
42 .FirstOrDefaultAsync(i => i.ItemId == id);
43 }
44
45 public async Task<bool> SaveInventoryItemAsync(InventoryItem item)
46 {
47 try
48 {
49 if (item.ItemId == 0)
50 {
51 await _dbContext.InventoryItems.AddAsync(item);
52 }
53 else
54 {
55 _dbContext.InventoryItems.Update(item);
56 }
57
58 await _dbContext.SaveChangesAsync();
59 return true;
60 }
61 catch
62 {
63 return false;
64 }
65 }
66 }
67}4. Afficher le modèle
1// ViewModels/InventoryItemViewModel.cs
2using CommunityToolkit.Mvvm.ComponentModel;
3using CommunityToolkit.Mvvm.Input;
4using InventoryApp.Models;
5using InventoryApp.Services;
6using System;
7using System.Collections.ObjectModel;
8using System.ComponentModel.DataAnnotations;
9using System.Threading.Tasks;
10using System.Windows;
11
12namespace InventoryApp.ViewModels
13{
14 public partial class InventoryItemViewModel : ObservableObject
15 {
16 private readonly IInventoryService _inventoryService;
17
18 [ObservableProperty]
19 private int _itemId;
20
21 [ObservableProperty]
22 [NotifyDataErrorInfo]
23 [Required(ErrorMessage = "Name is required")]
24 private string _name = string.Empty;
25
26 [ObservableProperty]
27 private string _description = string.Empty;
28
29 [ObservableProperty]
30 [NotifyDataErrorInfo]
31 [Range(0, int.MaxValue, ErrorMessage = "Quantity must be a positive number")]
32 private int _quantity;
33
34 [ObservableProperty]
35 [NotifyDataErrorInfo]
36 [Range(0, double.MaxValue, ErrorMessage = "Price must be a positive number")]
37 private decimal _price;
38
39 [ObservableProperty]
40 private Category? _selectedCategory;
41
42 [ObservableProperty]
43 private ObservableCollection<Category> _categories = new();
44
45 [ObservableProperty]
46 private bool _isLoading;
47
48 [ObservableProperty]
49 private string _windowTitle = "New Inventory Item";
50
51 public InventoryItemViewModel(IInventoryService inventoryService)
52 {
53 _inventoryService = inventoryService;
54 }
55
56 public async Task LoadDataAsync(int? itemId = null)
57 {
58 try
59 {
60 IsLoading = true;
61
62 // Load categories
63 var categoryList = await _inventoryService.GetCategoriesAsync();
64 Categories = new ObservableCollection<Category>(categoryList);
65
66 // If editing existing item
67 if (itemId.HasValue && itemId.Value > 0)
68 {
69 var item = await _inventoryService.GetInventoryItemAsync(itemId.Value);
70 if (item != null)
71 {
72 ItemId = item.ItemId;
73 Name = item.Name;
74 Description = item.Description;
75 Quantity = item.Quantity;
76 Price = item.Price;
77 SelectedCategory = Categories.FirstOrDefault(c => c.CategoryId == item.CategoryId);
78 WindowTitle = "Edit Inventory Item";
79 }
80 }
81 }
82 finally
83 {
84 IsLoading = false;
85 }
86 }
87
88 [RelayCommand]
89 private async Task SaveAsync()
90 {
91 if (SelectedCategory == null)
92 {
93 MessageBox.Show("Please select a category", "Validation Error", MessageBoxButton.OK, MessageBoxImage.Warning);
94 return;
95 }
96
97 var item = new InventoryItem
98 {
99 ItemId = ItemId,
100 Name = Name,
101 Description = Description,
102 CategoryId = SelectedCategory.CategoryId,
103 Quantity = Quantity,
104 Price = Price
105 };
106
107 var result = await _inventoryService.SaveInventoryItemAsync(item);
108 if (result)
109 {
110 MessageBox.Show(ItemId == 0 ? "Item added successfully" : "Item updated successfully",
111 "Success", MessageBoxButton.OK, MessageBoxImage.Information);
112 CloseWindow?.Invoke();
113 }
114 else
115 {
116 MessageBox.Show("Error saving item", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
117 }
118 }
119
120 [RelayCommand]
121 private void Cancel()
122 {
123 CloseWindow?.Invoke();
124 }
125
126 // Event to close the window
127 public Action? CloseWindow { get; set; }
128 }
129}5. Afficher
1<!-- Views/InventoryItemView.xaml -->
2<Window x:Class="InventoryApp.Views.InventoryItemView"
3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
6 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
7 xmlns:vm="clr-namespace:InventoryApp.ViewModels"
8 mc:Ignorable="d"
9 Title="{Binding WindowTitle}"
10 Height="450" Width="500"
11 WindowStartupLocation="CenterOwner">
12
13 <Window.Resources>
14 <Style TargetType="TextBlock">
15 <Setter Property="Margin" Value="0,5,0,2" />
16 </Style>
17 <Style TargetType="TextBox">
18 <Setter Property="Padding" Value="5" />
19 <Setter Property="Margin" Value="0,0,0,10" />
20 </Style>
21 <Style TargetType="ComboBox">
22 <Setter Property="Padding" Value="5" />
23 <Setter Property="Margin" Value="0,0,0,10" />
24 </Style>
25 <Style TargetType="Button">
26 <Setter Property="Padding" Value="15,5" />
27 <Setter Property="Margin" Value="5" />
28 <Setter Property="MinWidth" Value="80" />
29 </Style>
30 </Window.Resources>
31
32 <Grid Margin="20">
33 <Grid.RowDefinitions>
34 <RowDefinition Height="*" />
35 <RowDefinition Height="Auto" />
36 </Grid.RowDefinitions>
37
38 <StackPanel Grid.Row="0">
39 <TextBlock Text="Item Name:" />
40 <TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
41
42 <TextBlock Text="Description:" />
43 <TextBox Text="{Binding Description}" Height="60" TextWrapping="Wrap" AcceptsReturn="True" />
44
45 <TextBlock Text="Category:" />
46 <ComboBox ItemsSource="{Binding Categories}"
47 SelectedItem="{Binding SelectedCategory}"
48 DisplayMemberPath="CategoryName" />
49
50 <TextBlock Text="Quantity:" />
51 <TextBox Text="{Binding Quantity, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
52
53 <TextBlock Text="Price:" />
54 <TextBox Text="{Binding Price, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
55 </StackPanel>
56
57 <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right">
58 <Button Content="Save" Command="{Binding SaveCommand}" />
59 <Button Content="Cancel" Command="{Binding CancelCommand}" />
60 </StackPanel>
61
62 <Grid Grid.RowSpan="2" Background="#80000000" Visibility="{Binding IsLoading, Converter={StaticResource BooleanToVisibilityConverter}}">
63 <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
64 <TextBlock Text="Loading..." Foreground="White" FontSize="16" HorizontalAlignment="Center" />
65 <ProgressBar IsIndeterminate="True" Width="200" Height="20" Margin="0,10,0,0" />
66 </StackPanel>
67 </Grid>
68 </Grid>
69</Window>1// Views/InventoryItemView.xaml.cs
2using InventoryApp.ViewModels;
3using System.Windows;
4
5namespace InventoryApp.Views
6{
7 public partial class InventoryItemView : Window
8 {
9 private readonly InventoryItemViewModel _viewModel;
10
11 public InventoryItemView(InventoryItemViewModel viewModel, int? itemId = null)
12 {
13 InitializeComponent();
14 _viewModel = viewModel;
15 DataContext = _viewModel;
16
17 _viewModel.CloseWindow = () => Close();
18
19 Loaded += async (s, e) =>
20 {
21 await _viewModel.LoadDataAsync(itemId);
22 };
23 }
24 }
25}6. Démarrage de l'application et configuration DI
1// App.xaml.cs
2using InventoryApp.Data;
3using InventoryApp.Services;
4using InventoryApp.ViewModels;
5using InventoryApp.Views;
6using Microsoft.EntityFrameworkCore;
7using Microsoft.Extensions.DependencyInjection;
8using Microsoft.Extensions.Hosting;
9using System.Windows;
10
11namespace InventoryApp
12{
13 public partial class App : Application
14 {
15 private readonly IHost _host;
16
17 public App()
18 {
19 _host = Host.CreateDefaultBuilder()
20 .ConfigureServices((context, services) =>
21 {
22 // Register DbContext
23 services.AddDbContext<AppDbContext>(options =>
24 options.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=InventoryApp;Trusted_Connection=True;"));
25
26 // Register services
27 services.AddScoped<IInventoryService, InventoryService>();
28
29 // Register ViewModels
30 services.AddTransient<InventoryItemViewModel>();
31
32 // Register Views
33 services.AddTransient<InventoryItemView>();
34 services.AddTransient<MainWindow>();
35 })
36 .Build();
37 }
38
39 protected override void OnStartup(StartupEventArgs e)
40 {
41 _host.Start();
42
43 var mainWindow = _host.Services.GetRequiredService<MainWindow>();
44 mainWindow.Show();
45
46 base.OnStartup(e);
47 }
48
49 protected override void OnExit(ExitEventArgs e)
50 {
51 _host.Dispose();
52 base.OnExit(e);
53 }
54 }
55}Principales améliorations apportées à la migration
- Architecture moderne
- Modèle MVVM avec séparation claire des préoccupations
- Injection de dépendances pour une meilleure testabilité
- Synchronisation et attente d'une interface utilisateur réactive
- Accès aux données
- Entity Framework Core au lieu d'ADO.NET
- Requêtes paramétrées pour empêcher l'injection SQL
- Modèle de référentiel pour l'accès aux données
- Amélioration de l'interface utilisateur
- Style et modèles WPF
- Liaison de données avec validation
- Indicateurs de chargement pour les opérations asynchrones
- Qualité du code
- Dactylographie forte au lieu de types de variantes
- Gestion appropriée des erreurs
- Validation des entrées à l'aide d'annotations de données
- Maintenabilité
- Structure de projet organisée
- Composants testables
- Fonctionnalités modernes du langage C#
Cette approche de migration fournit une base solide pour moderniser votre application d'inventaire VB6 tout en préservant ses fonctionnalités de base et en l'améliorant grâce à des pratiques de développement modernes.
Explorez les cas d'utilisation associés
Découvrez l'assistant IA de Ninja
Essayez gratuitement dès aujourd'hui. Forfaits à partir de 19$ par mois.


