ASP.NET MVC中多对多关注关系下User实体保存后字段为空问题求助
Hey there! Let's break down what's going on here and fix your follower/following issue step by step.
1. Fix the EF Core Many-to-Many Configuration
Your current OnModelCreating uses EF6-style mapping (Map method), which doesn’t work the same way in EF Core. Since you have a Subcribe entity (your join table for the follow relationship), you need to configure the relationship explicitly with this intermediate entity instead of relying on the old EF6 syntax. Also, note that EF Core uses ModelBuilder instead of DbModelBuilder—that’s an easy mixup when coming from EF6!
Update your OnModelCreating method:
protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // Don't forget this for IdentityUser setup // Configure the Subcribe join entity's composite key modelBuilder.Entity<Subcribe>() .HasKey(s => new { s.UserId, s.FollowedById }); // Link Subcribe to the follower (current user) modelBuilder.Entity<Subcribe>() .HasOne(s => s.User) .WithMany(u => u.Following) .HasForeignKey(s => s.UserId); // Link Subcribe to the followed user (target user) modelBuilder.Entity<Subcribe>() .HasOne(s => s.FollowedBy) .WithMany(u => u.Followers) .HasForeignKey(s => s.FollowedById); }
Make sure your Subcribe entity has matching foreign key properties:
public class Subcribe { public string UserId { get; set; } // ID of the user who is following public User User { get; set; } public string FollowedById { get; set; } // ID of the user being followed public User FollowedBy { get; set; } }
2. Simplify Your Follow Method
You’re doing redundant work here—EF Core automatically tracks changes to entities you fetch from the database, so you don’t need to call Update on user and currentUser. Also, since we’re using the Subcribe join entity, you only need to add a new Subcribe record to establish the follow relationship:
public async Task<IActionResult> Follow(string Id) { var targetUser = await _db.ContextUser.FindAsync(Id); var currentUser = await CurrentUser(); // Switch to async to avoid deadlocks from .Result // Prevent duplicate follow records var alreadyFollowing = _db.Subcribes.Any(s => s.UserId == currentUser.Id && s.FollowedById == targetUser.Id); if (!alreadyFollowing) { var newSubscription = new Subcribe { UserId = currentUser.Id, FollowedById = targetUser.Id }; _db.Subcribes.Add(newSubscription); await _db.SaveChangesAsync(); } return RedirectToAction("Personal", "Post", new { Id = Id }); }
3. Load Navigation Properties in Personal Method
The main issue you’re seeing is that EF Core doesn’t load related collections (like Followers and Following) by default. You need to explicitly eager-load these relationships using Include when fetching the user:
public async Task<IActionResult> Personal(string Id) { var user = await _db.ContextUser .Include(u => u.Followers) // Load the user's followers .Include(u => u.Following) // Load the users this user is following .Include(u => u.Posts) // Load the user's posts (no need to do this manually anymore) .FirstOrDefaultAsync(u => u.Id == Id); if (user == null) { return NotFound(); // Handle cases where the user doesn't exist } return View(user); }
This ensures that when you pass the user to your view, Followers and Following will be populated with the actual related data from the database.
4. Optional: Enable Lazy Loading (If You Prefer)
If you want EF Core to automatically load navigation properties when you access them (instead of using Include every time), you can enable lazy loading:
- Install the
Microsoft.EntityFrameworkCore.ProxiesNuGet package - Add
.UseLazyLoadingProxies()when configuring your DbContext (inProgram.csorStartup.cs):
services.AddDbContext<YourDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("YourConnection")) .UseLazyLoadingProxies());
- Make your navigation properties
virtualin theUserclass:
public class User : IdentityUser { // ... your existing properties public virtual ICollection<User> Followers { get; set; } public virtual ICollection<User> Following { get; set; } public virtual List<Post> Posts { get; set; } }
Eager loading with Include is often more predictable for performance, but lazy loading can be convenient for simpler scenarios.
Why Your Original Code Wasn’t Working
- The EF6-style
Mapconfiguration didn’t set up the relationship correctly in EF Core, so navigation properties weren’t tracked properly. - In
Personal, you weren’t includingFollowersandFollowingin your query, so EF Core never fetched that data from the database. - Calling
Updateon entities EF Core was already tracking was unnecessary and could cause unexpected behavior.
Give these changes a try—this should resolve the issue where your Followers and Following fields are empty in the Personal view.
内容的提问来源于stack exchange,提问作者Huzker122

