英文:
ASP.NET Core 6 MVC C# Seeding many to many relationships using seeder not onModelCreating
问题
I understand that you want a translation of the code provided. Here is the translation:
我在联系人和类别之间建立了多对多的关系。LINQ已经创建了SQL连接表 `CategoryContact`。我尝试了多种不同的方法来尝试将类别分配给联系人,但都没有成功。大多数在线信息都是关于如何在 `OnModelCreating` 方法中执行此操作的,但我没有找到关于如何在种子类中执行此操作的任何信息。
以下是我尝试的一些示例...
await _dbContext.Categories.Add(contactId).ToString();
category.Add(contact);
foreach (int categoryId in CategoryList)
{
await _addressBookService.AddContactToCategoryAsync(categoryId, contact.Id);
}
上述所有方法都因无法成功调试而无法工作。
基本上,我想为每个联系人分配一个类别,以便联系人在种子中附加/分配了一个类别。
任何帮助都将不胜感激。
以下是代码。
种子类
```csharp
using ContactPro.Data;
using ContactPro.Models;
using Microsoft.AspNetCore.Identity;
namespace ContactPro.Helpers
{
public class DataSeeder
{
private readonly ApplicationDbContext _dbContext;
private readonly UserManager<AppUser> _userManager;
private string? appUserId;
List<Contact> contact = new List<Contact>();
List<Category> category = new List<Category>();
public DataSeeder(ApplicationDbContext dbContext, UserManager<AppUser> userManager)
{
_dbContext = dbContext;
_userManager = userManager;
}
public async Task SeedDataAsync()
{
await SeedUsersAsync();
await SeedContactsAsync();
await SeedCategoriesAsync();
}
// 其余部分未提供,请查看原始代码。
}
}
联系人模型(仅包括相关属性)
public class Contact
{
public int Id { get; set; }
[Required]
public string? AppUserId { get; set; }
// virtual
public virtual AppUser? AppUser { get; set; }
public ICollection<Category> Categories { get; set; } = new HashSet<Category>();
}
类别模型
public class Category
{
public int Id { get; set; }
[Required]
public string? AppUserId { get; set; }
[Required]
[Display(Name = "Category Name")]
public string? Name { get; set; }
public virtual AppUser? AppUser { get; set; }
public virtual ICollection<Contact> Contacts { get; set; } = new HashSet<Contact>();
}
请注意,这只是代码的翻译部分,不包括其他问题或答案。如果您需要进一步的帮助,请告诉我。
英文:
I have a many to many relationship between contacts and categories. LINQ has created the SQL junction table CategoryContact
. I have tried several different things to try to assign categories to contacts but haven't had any success. Most of the info online is how to do this with the OnModelCreating
method, but I haven't found anything on how to do this in a seeder class.
Here are a few samples of things I tried...
await _dbContext.Categories.Add(contactId).ToString();
category.Add(contact);
foreach (int categoryId in CategoryList)
{
await _addressBookService.AddContactToCategoryAsync(categoryId, contact.Id);
}
All of the above didn't work for reasons I was unable to successfully debug.
Basically I want to assign one of the categories to each contact so the contacts are seeded with a category attached/assigned.
Any help would be greatly appreciated.
Here is the code.
Seeder class
using ContactPro.Data;
using ContactPro.Models;
using Microsoft.AspNetCore.Identity;
namespace ContactPro.Helpers
{
public class DataSeeder
{
private readonly ApplicationDbContext _dbContext;
private readonly UserManager<AppUser> _userManager;
private string? appUserId;
List<Contact> contact = new List<Contact>();
List<Category> category = new List<Category>();
public DataSeeder(ApplicationDbContext dbContext, UserManager<AppUser> userManager)
{
_dbContext = dbContext;
_userManager = userManager;
}
public async Task SeedDataAsync()
{
await SeedUsersAsync();
await SeedContactsAsync();
await SeedCategoriesAsync();
}
private async Task SeedUsersAsync()
{
if (!_dbContext.Users.Any())
{
var demoUser = new AppUser()
{
UserName = "demouser@mail.com",
Email = "demouser@mail.com",
FirstName = "Demo",
LastName = "User",
EmailConfirmed = true
};
await _userManager.CreateAsync(demoUser, "xxxxxx");
}
await _dbContext.SaveChangesAsync();
appUserId = (await _userManager.FindByEmailAsync("demouser@mail.com")).Id;
}
private async Task SeedContactsAsync()
{
try
{
if (!_dbContext.Contacts.Any())
{
contact = new List<Contact>()
{
new Contact()
{
FirstName = "John",
LastName = "Dickens",
Address1 = "12 Main St.",
City = "Concord",
States = ContactPro.Enums.States.NH,
ZipCode = 03101,
Email = "john@mail.com",
BirthDate = new DateTime(1994,8,20),
PhoneNumber = "(212)345-8587",
DateCreated = new DateTime(2023,5,20),
AppUserId = appUserId,
}
};
}
await _dbContext.Contacts.AddRangeAsync(contact);
await _dbContext.SaveChangesAsync();
}
catch (Exception ex)
{
Console.WriteLine("************* ERROR *************");
Console.WriteLine("Error Seeding Contacts.");
Console.WriteLine(ex.Message);
Console.WriteLine("***********************************");
throw;
}
}
private async Task SeedCategoriesAsync()
{
if (!_dbContext.Categories.Any())
{
category = new List<Category>()
{
new Category()
{
AppUserId = appUserId,
Name = "_UnCategorized",
},
new Category()
{
Name = "Friend",
AppUserId = appUserId
},
new Category()
{
Name = "Colleague",
AppUserId = appUserId
},
new Category()
{
Name = "Vendor",
AppUserId = appUserId
},
new Category()
{
Name = "Contractor",
AppUserId = appUserId
},
new Category()
{
Name = "Send Invitation",
AppUserId = appUserId
}
};
}
await _dbContext.Categories.AddRangeAsync(category);
await _dbContext.SaveChangesAsync();
}
}
}
Contact model (only included relevant properties)
public class Contact
{
public int Id { get; set; }
[Required]
public string? AppUserId { get; set; }
// virtual
public virtual AppUser? AppUser { get; set; }
public ICollection<Category> Categories { get; set; } = new HashSet<Category>();
}
Category model
public class Category
{
public int Id { get; set; }
[Required]
public string? AppUserId { get; set; }
[Required]
[Display(Name = "Category Name")]
public string? Name { get; set; }
public virtual AppUser? AppUser { get; set; }
public virtual ICollection<Contact> Contacts { get; set; } = new HashSet<Contact>();
}
答案1
得分: 1
Here is the translated code portion:
**Update2:**
如果您有多个`Contact`,您需要单独指定`Category`。请参考以下代码:
```csharp
public class DataSeeder
{
public static async Task InitializeAsync(IServiceProvider serviceProvider)
{
var context = new ApplicationDbContext(serviceProvider.GetRequiredService<DbContextOptions<ApplicationDbContext>>());
var userManager = serviceProvider.GetRequiredService<UserManager<AppUser>>();
string? appUserId;
List<Contact> contact = new List<Contact>();
List<Category> category = new List<Category>();
using (context)
{
if (!context.Users.Any())
{
var demoUser = new AppUser()
{
UserName = "demouser@mail.com",
Email = "demouser@mail.com",
FirstName = "Demo",
LastName = "User",
EmailConfirmed = true
};
await userManager.CreateAsync(demoUser, "Aa12345!");
}
await context.SaveChangesAsync();
appUserId = (await userManager.FindByEmailAsync("demouser@mail.com")).Id;
try
{
if (!context.Contacts.Any())
{
contact = new List<Contact>()
{
new Contact()
{
FirstName = "John",
LastName = "Dickens",
City = "Concord",
Email = "john@mail.com",
BirthDate = new DateTime(1994,8,20),
PhoneNumber = "(212)345-8587",
DateCreated = new DateTime(2023,5,20),
AppUserId = appUserId,
},
new Contact()
{
FirstName = "Tom",
LastName = "Smith",
City = "Concord",
Email = "tom@mail.com",
BirthDate = new DateTime(1994,8,20),
PhoneNumber = "(212)345-8587",
DateCreated = new DateTime(2023,5,20),
AppUserId = appUserId,
}
};
await context.Contacts.AddRangeAsync(contact);
await context.SaveChangesAsync();
}
}
catch (Exception ex)
{
Console.WriteLine("************* ERROR ************");
Console.WriteLine("Error Seeding Contacts.");
Console.WriteLine(ex.Message);
Console.WriteLine("***********************************");
throw;
}
if (!context.Categories.Any())
{
category = new List<Category>()
{
new Category()
{
AppUserId = appUserId,
Name = "_UnCategorized"
},
new Category()
{
Name = "Friend",
AppUserId = appUserId
},
new Category()
{
Name = "Colleague",
AppUserId = appUserId
},
new Category()
{
Name = "Vendor",
AppUserId = appUserId
},
new Category()
{
Name = "Contractor",
AppUserId = appUserId
},
new Category()
{
Name = "Send Invitation",
AppUserId = appUserId
}
};
}
contact[0].Categories = new List<Category>();
contact[0].Categories.Add(category.Find(c => c.Name == "Contractor"));
contact[1].Categories = new List<Category>();
contact[1].Categories.Add(category.Find(c => c.Name == "Vendor"));
context.Contacts.Update(contact[0]);
context.Contacts.Update(contact[1]);
await context.Categories.AddRangeAsync(category);
await context.SaveChangesAsync();
}
}
}
Test Result:
[![enter image description here][1]][1]
Please note that this code is in C#, and it appears to be part of a data seeding process for an application. If you have any specific questions or need further assistance, please feel free to ask.
[1]: https://i.stack.imgur.com/EZAw5.png
<details>
<summary>英文:</summary>
**Update2:**
If you have multiple `Contact`, you need to specify `Category` separately. Please refer to the code below:
public class DataSeeder
{
public static async Task InitializeAsync(IServiceProvider serviceProvider)
{
var context = new ApplicationDbContext(serviceProvider.GetRequiredService<DbContextOptions<ApplicationDbContext>>());
var userManager = serviceProvider.GetRequiredService<UserManager<AppUser>>();
string? appUserId;
List<Contact> contact = new List<Contact>();
List<Category> category = new List<Category>();
using (context)
{
if (!context.Users.Any())
{
var demoUser = new AppUser()
{
UserName = "demouser@mail.com",
Email = "demouser@mail.com",
FirstName = "Demo",
LastName = "User",
EmailConfirmed = true
};
await userManager.CreateAsync(demoUser, "Aa12345!");
}
await context.SaveChangesAsync();
appUserId = (await userManager.FindByEmailAsync("demouser@mail.com")).Id;
try
{
if (!context.Contacts.Any())
{
contact = new List<Contact>()
{
new Contact()
{
FirstName = "John",
LastName = "Dickens",
City = "Concord",
Email = "john@mail.com",
BirthDate = new DateTime(1994,8,20),
PhoneNumber = "(212)345-8587",
DateCreated = new DateTime(2023,5,20),
AppUserId = appUserId,
},
new Contact()
{
FirstName = "Tom",
LastName = "Smith",
City = "Concord",
Email = "tom@mail.com",
BirthDate = new DateTime(1994,8,20),
PhoneNumber = "(212)345-8587",
DateCreated = new DateTime(2023,5,20),
AppUserId = appUserId,
}
};
await context.Contacts.AddRangeAsync(contact);
await context.SaveChangesAsync();
}
}
catch (Exception ex)
{
Console.WriteLine("************* ERROR ************");
Console.WriteLine("Error Seeding Contacts.");
Console.WriteLine(ex.Message);
Console.WriteLine("***********************************");
throw;
}
if (!context.Categories.Any())
{
category = new List<Category>()
{
new Category()
{
AppUserId = appUserId,
Name = "_UnCategorized"
},
new Category()
{
Name = "Friend",
AppUserId = appUserId
},
new Category()
{
Name = "Colleague",
AppUserId = appUserId
},
new Category()
{
Name = "Vendor",
AppUserId = appUserId
},
new Category()
{
Name = "Contractor",
AppUserId = appUserId
},
new Category()
{
Name = "Send Invitation",
AppUserId = appUserId
}
};
}
contact[0].Categories = new List<Category>();
contact[0].Categories.Add(category.Find(c => c.Name == "Contractor"));
contact[1].Categories = new List<Category>();
contact[1].Categories.Add(category.Find(c => c.Name == "Vendor"));
context.Contacts.Update(contact[0]);
context.Contacts.Update(contact[1]);
await context.Categories.AddRangeAsync(category);
await context.SaveChangesAsync();
}
}
}
Test Result:
[![enter image description here][1]][1]
********************************************************************
**Update:**
You mean that the `CategoryContact` table is generated after migrating to the database, which contains `ContactId` and `CategoryId` as the primary key, but it is not filled with data, right?
This is because you didn't populate the `Categories` property in `Contact` and the `Contacts` property in `Category`.
Take my code as an example,I added a `new Contact()` to operate on the `Categories` property and update the database at the end:
public class DataSeeder
{
public static async Task InitializeAsync(IServiceProvider serviceProvider)
{
var context = new ApplicationDbContext(serviceProvider.GetRequiredService<DbContextOptions<ApplicationDbContext>>());
var userManager = serviceProvider.GetRequiredService<UserManager<AppUser>>();
string? appUserId;
//Add this line
var contactItem = new Contact();
List<Contact> contact = new List<Contact>();
List<Category> category = new List<Category>();
using (context)
{
if (!context.Users.Any())
{
var demoUser = new AppUser()
{
UserName = "demouser@mail.com",
Email = "demouser@mail.com",
FirstName = "Demo",
LastName = "User",
EmailConfirmed = true
};
await userManager.CreateAsync(demoUser, "Aa12345!");
}
await context.SaveChangesAsync();
appUserId = (await userManager.FindByEmailAsync("demouser@mail.com")).Id;
try
{
if (!context.Contacts.Any())
{
contactItem = new Contact()
{
FirstName = "John",
LastName = "Dickens",
City = "Concord",
Email = "john@mail.com",
BirthDate = new DateTime(1994, 8, 20),
PhoneNumber = "(212)345-8587",
DateCreated = new DateTime(2023, 5, 20),
AppUserId = appUserId,
};
}
}
catch (Exception ex)
{
Console.WriteLine("************* ERROR *************");
Console.WriteLine("Error Seeding Contacts.");
Console.WriteLine(ex.Message);
Console.WriteLine("***********************************");
throw;
}
if (!context.Categories.Any())
{
category = new List<Category>()
{
new Category()
{
AppUserId = appUserId,
Name = "_UnCategorized",
Contacts = contact
},
new Category()
{
Name = "Friend",
AppUserId = appUserId,
Contacts = contact
},
new Category()
{
Name = "Colleague",
AppUserId = appUserId,
Contacts = contact
},
new Category()
{
Name = "Vendor",
AppUserId = appUserId,
Contacts = contact
},
new Category()
{
Name = "Contractor",
AppUserId = appUserId,
Contacts = contact
},
new Category()
{
Name = "Send Invitation",
AppUserId = appUserId,
Contacts = contact
}
};
}
//Operate the database at the end
contactItem.Categories = category;
contact.Add(contactItem);
await context.Contacts.AddRangeAsync(contact);
await context.Categories.AddRangeAsync(category);
await context.SaveChangesAsync();
}
}
}
Test Result:
[![enter image description here][2]][2]
****************************************************************
Is your `DataSeeder` running successfully? I modified your code according to this [official documentation](https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/working-with-sql?view=aspnetcore-7.0&tabs=visual-studio#seed-the-database) and it works.
DataSeeder.cs:
public class DataSeeder
{
public static async Task InitializeAsync(IServiceProvider serviceProvider)
{
var context = new ApplicationDbContext(serviceProvider.GetRequiredService<DbContextOptions<ApplicationDbContext>>());
var userManager = serviceProvider.GetRequiredService<UserManager<AppUser>>();
string? appUserId;
List<Contact> contact = new List<Contact>();
List<Category> category = new List<Category>();
using (context)
{
if (!context.Users.Any())
{
var demoUser = new AppUser()
{
UserName = "demouser@mail.com",
Email = "demouser@mail.com",
FirstName = "Demo",
LastName = "User",
EmailConfirmed = true
};
await userManager.CreateAsync(demoUser, "Aa12345!");
}
await context.SaveChangesAsync();
appUserId = (await userManager.FindByEmailAsync("demouser@mail.com")).Id;
try
{
if (!context.Contacts.Any())
{
contact = new List<Contact>()
{
new Contact()
{
FirstName = "John",
LastName = "Dickens",
City = "Concord",
Email = "john@mail.com",
BirthDate = new DateTime(1994,8,20),
PhoneNumber = "(212)345-8587",
DateCreated = new DateTime(2023,5,20),
AppUserId = appUserId,
}
};
}
await context.Contacts.AddRangeAsync(contact);
await context.SaveChangesAsync();
}
catch (Exception ex)
{
Console.WriteLine("************* ERROR *************");
Console.WriteLine("Error Seeding Contacts.");
Console.WriteLine(ex.Message);
Console.WriteLine("***********************************");
throw;
}
if (!context.Categories.Any())
{
category = new List<Category>()
{
new Category()
{
AppUserId = appUserId,
Name = "_UnCategorized",
},
new Category()
{
Name = "Friend",
AppUserId = appUserId
},
new Category()
{
Name = "Colleague",
AppUserId = appUserId
},
new Category()
{
Name = "Vendor",
AppUserId = appUserId
},
new Category()
{
Name = "Contractor",
AppUserId = appUserId
},
new Category()
{
Name = "Send Invitation",
AppUserId = appUserId
}
};
}
await context.Categories.AddRangeAsync(category);
await context.SaveChangesAsync();
}
}
}
Program.cs:
var app = builder.Build();
using (var scope = app.Services.CreateScope())
{
var services = scope.ServiceProvider;
await DataSeeder.InitializeAsync(services);
}
After [migrating and updating the database](https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/adding-model?view=aspnetcore-7.0&tabs=visual-studio#initial-migration), run the project, the data is successfully added to the database.
[1]: https://i.stack.imgur.com/EZAw5.png
[2]: https://i.stack.imgur.com/m1N0d.png
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论