include user data in query - asp.net

I would like to query a table, which holds workflow events with the appr. user id. And instead of the user id, I would like to show the user name.
I have this model:
public class WorkflowEvent
{
public long Id { get; set; }
public DateTime EventDate { get; set; }
public WorkflowStatus Status { get; set; }
public int UserId { get; set; }
public AppUser User { get; }
public string Note { get; set; }
public long WorkflowId { get; set; }
public long DocumentId { get; set; }
}
And this is the user model (it is the standard IdentityUser, I use Asp.Net Identity):
public class AppUser : IdentityUser<int>
{
public string RealName { get; set; }
public string AppTheme { get; set; }
}
And this is my query:
public IEnumerable<WorkflowEvent> WorkflowEvents(int DocumentId)
{
return DataContext.WorkflowEvents.Where(e => e.DocumentId == DocumentId).Include(e => e.User).OrderBy(e => e.EventDate);
}
Unfortunatelly, I get following error on this: System.InvalidOperationException: Lambda expression used inside Include is not valid. In the WorkflowEvents table, there is a foreign key on the UserId, of course.
Have you any idea, why do I get this error message? What goes wrong?

Both Sami's and Nik's suggestions helped. I added the setter to the AppUser. And then I got the error, that the AppUser object isn't exists. This due to the fact, that I have in my app two datacontexts: one for the domain models and one for Identity. So, I just add this line of code to the domain data context:
public DbSet<AppUser> AspNetUsers { get; set; }
And everything worked like a charm.

Related

Establishing one to one relations with Entity Framework 7

Having the following parent class:
[Table("smart_recharge_registro")]
public class SmartRechargeRegistro
{
[Key]
public int id { get; set; }
public SmartRechargeRequest request { get; set; }
public SmartRechargeProceso proceso { get; set; }
public SmartRechargeResponse response { get; set; }
}
Which in turn references the following child classes:
[Table("smart_recharge_request")]
public class SmartRechargeRequest
{
public String nombreDeUsuario { get; set; }
public String passwordDeUsuario { get; set; }
public String msisdnSuscriptor { get; set; }
}
and:
[Table("smart_recharge_proceso")]
public class SmartRechargeProceso
{
[Key]
public int id { get; set; }
public String carrierId { get; set; }
public String cliente { get; set; }
public String network { get; set; }
}
and lastly:
[Table("smart_recharge_response")]
public class SmartRechargeResponse
{
public Boolean responseSuccess { get; set; }
public int responseCode { get; set; }
public String? responseDetails { get; set; }
}
The Add-Migration and Update-Database command execute without problems. However, when I try to save
await _repository.RegistroColeccion.AddAsync(registro);
await _repositorio.SaveChangesAsync();
I get the following error:
Microsoft.EntityFrameworkCore.DbUpdateException: Could not save changes. Please configure your entity type accordingly.
---> MySql.Data.MySqlClient.MySqlException (0x80004005): Cannot add
or update a child row: a foreign key constraint fails
(beservicebroker_dev.registro_eventos_srdotnet, CONSTRAINT
FK_registro_eventos_srdotnet_SmartRechargeProceso_procesoid FOREIGN
KEY (procesoid) REFERENCES smartrechargeproceso (id) O)
To solve the problem, I tried to create one-to-one relationships following this tutorial
modelBuilder.Entity<SmartRechargeRegistro>()
.HasOne(s => s.request)
.WithOne(r => r.SmartRechargeRegistro)
.HasForeignKey<SmartRechargeRequest>(r => r.id);
modelBuilder.Entity<SmartRechargeRegistro>()
.HasOne(s => s.proceso)
.WithOne(p => p.SmartRechargeRegistro)
.HasForeignKey<SmartRechargeProceso>(p => p.id);
modelBuilder.Entity<SmartRechargeRegistro>()
.HasOne(s => s.response)
.WithOne(r => r.SmartRechargeRegistro)
.HasForeignKey<SmartRechargeResponse>(r => r.id);
Inside SmartRechargeRequest, SmartRechargeProceso and SmartRechargeResponse, added the following:
[JsonIgnore]
public SmartRechargeRegistro SmartRechargeRegistro { get; set; }
Also added inside SmartRechargeRequest and SmartRechargeResponse an id
[Key]
public int id { get; set; }
I'm still unable to test the endpoint because the SmartRechargeRequest and SmartRechargeResponse are completely disfigured in the swagger (even if the [JsonIgnore] or [IgnoreDataMember] annotations are set) due to the presence of that SmartRechargeRegistro object.
I'm pretty sure my solution is misguided and I'm getting the process completely wrong.
What would be the proper way to map one-to-one relationships for this case? Any help will be appreciated.
Please note that in reality, these classes are huge (dozens of properties), so it's not possible to merge all of them on a single table.

Introducing FOREIGN KEY constraint on table may cause cycles or multiple cascade paths even after removing the affected field completely

I'm quite new to .net and entity framework (this is my first project) and I'm getting the following error when trying to update the database:
*Introducing FOREIGN KEY constraint 'FK_Rating_User_UserId' on table 'Rating' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint or index. See previous errors.*
I tried doing what it says (at least I think so) by adding the following to my dbContext class:
protected override void OnModelCreating(ModelBuilder modelbuilder)
{
modelbuilder.Entity<Rating>().HasOne(u => u.User).WithMany().OnDelete(DeleteBehavior.Restrict);
modelbuilder.Entity<Rating>().HasOne(g => g.Game).WithMany().OnDelete(DeleteBehavior.Restrict);
}
Not sure have I formulated that method correctly but it did not help (I tried with different DeleteBehavior like SetNull and NoAction)
The thing that really got me confused is that the issue appears even after removing all fields related to other tables from Rating class or even all references between all classes.
My Rating class:
public class Rating
{
public long RatingId { get; set; }
//[Rating]
public virtual Game Game { get; set; } // issue appears even after removing this and User line
//[Rating]
public int Score { get; set; }
public string CommentTitle { get; set; }
public string CommentDescription { get; set; }
//[Rating]
public virtual User User { get; set; }// issue appears even after removing this and Game line
}
User class:
public class User
{
public long UserId { get; set; }
//[Required]
public bool IsModerator { get; set; }
//[Required]
public string Username { get; set; }
//[Required]
public string Email { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
//[Required]
public string Password { get; set; }
//[Required]
public string Salt { get; set; }
public string Description { get; set; }
}
Game class:
public class Game
{
public long GameId { get; set; }
//[Required]
public virtual User User { get; set; }
//[Required]
public string Title { get; set; }
public string Description { get; set; }
//[Required]
public string PricingType { get; set; }
public float MinDonation { get; set; }
public float MaxDonation { get; set; }
//[Required]
public string FileLocation { get; set; }
public float AverageRaiting { get; set; }
public int DownloadCount { get; set; }
}
GameImage class (probably unrelated to the issue just wanted to give a full context)
public class GameImage
{
public long GameImageId { get; set; }
//[Required]
public virtual Game Game { get; set; }
//[Required]
public string Location { get; set; }
//[Required]
public bool IsThumbnail { get; set; }
}
dbContext class:
public class dbContext : DbContext
{
public dbContext(DbContextOptions<dbContext> options) : base(options)
{
}
public DbSet<User> User { get; set; }
public DbSet<Rating> Rating { get; set; }
public DbSet<GameImage> GameImage { get; set; }
public DbSet<Game> Game { get; set; }
}
The issue only appeared after I tried to update the database. The first few migrations and updates were ok, however, then I tried adding [Required] annotation (you can see them commented in the above code) as I noticed that most of the fields were created as nullable in my database - after that the issue starting to occur even after removing the annotations.
In case that matters, I'm using Visual Studio 2019 and SQL Server Express
Does anyone have any idea what may be the cause of this?
Edit:
Image of of my database schema diagram from SSMS
As you can see in the database schema it's visible that there are indeed cycles in the database, however, I cannot get rid of them as Entity Framework's command "Update-Database" does not update the DB and just throws the error mentioned above.
Based on my test, you can try the following steps to solve the problem.
First, please change your dbcontext class into the following code.
public class dbContext : DbContext
{
public dbContext() : base("name=MyContext") { }
public DbSet<User> User { get; set; }
public DbSet<Rating> Rating { get; set; }
public DbSet<GameImage> GameImage { get; set; }
public DbSet<Game> Game { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
}
}
Second, please delete all the tables the database.
Third, please try the following command in your package console.
PM> Update-Database -Force
Finally, you can see the new tables in the databse.

ASP.NET Core Conflict with Foreign Key

I have got several models:
Course.cs
public class Course
{
public Guid Id { get; set; }
public ICollection<ApplicationUser> Teacher { get; set; }
public string Name { get; set; }
public string ShortName { get; set; }
public DateTime CreationDate { get; set; }
public bool IsActive { get; set; }
}
Group.cs
public class Group
{
public Guid Id { get; set; }
public ApplicationUser Mentor { get; set;}
public string DisplayName { get; set; }
public string GroupName { get; set; }
public DateTime StartYear { get; set; }
public string InviteCode { get; set; }
public ICollection<ApplicationUser> Students { get; set; }
public ICollection<Course> Courses { get; set; }
}
ApplicationUser.cs
public class ApplicationUser : IdentityUser
{
[Required]
public string Firstname { get; set; }
[Required]
public string Surname { get; set; }
public bool Gender { get; set; }
public DateTime Birthdate { get; set; }
//[Required]
public string InviteCode { get; set; }
public Guid GroupId { get; set; }
[ForeignKey("GroupId")]
public Group CurrentGroup { get; set; }
public ICollection<Group> PastGroups { get; set; }
}
Now when I try to register (using Identity) a user (not even trying to give the user a group) I receive this error:
SqlException: The INSERT statement conflicted with the FOREIGN KEY
constraint "FK_AspNetUsers_Groups_GroupId". The conflict occurred in
database "aspnet-Project_Dojo-3af15f80-8c62-40a6-9850-ee7a296d0726",
table "dbo.Groups", column 'Id'. The statement has been terminated.
In my modelBuilder I have added some logics for the relations between Group, ApplicationUser (Students) and the Foreign Key:
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Customize the ASP.NET Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);\\
builder.Entity<ApplicationUser>()
.HasOne(p => p.CurrentGroup)
.WithMany(b => b.Students)
.HasForeignKey(p => p.GroupId);
}
I don't know what this is exactly doing, but I've been browsing some Stackoverflow threads to come to this code (migrations weren't working without it).
I look forward to a solution for my problem. Once again, I'm not doing ANYTHING with the groups yet when registering.
Thanks in advance!
not even trying to give the user a group
Well there's your problem, it's required.
Either provide a group, or make it optional by making the foreign key nullable (Guid? GroupId).
Because it's currently a non-nullable struct, it'll have a default value of all zeroes (Guid.Empty). This FK is not known in your database, resulting in the error you see.

How to overload an Odata V2 controller method to accept multiple values as parameters?

I am new in ASP.NET MVC web development. I am just trying to overload a simple odata controller method for several days but failing again and again. I want to know the mystery behind this. Please help me...
This is my EducationInfo Model class...
public partial class EducationInfo
{
[Key]
public int EducationID { get; set; }
[ForeignKey("UserID")]
public int UserID { get; set; }
[Required]
public string Title { get; set; }
[Required]
[StringLength(50)]
public string EducationLevel { get; set; }
public string Department_Group { get; set; }
public string InstituteName { get; set; }
[Required]
public string Board_University_Name { get; set; }
[StringLength(30)]
public string Duration { get; set; }
public DateTime PassingYear { get; set; }
[StringLength(30)]
public string Result { get; set; }
public virtual UserInfo UserInfo { get; set; }
}
And here is one of my EducationInfoesController GET methods which accepts EducationID as parameter
// GET: odata/EducationInfoes(5)
[EnableQuery]
public SingleResult<EducationInfo> GetEducationInfo([FromODataUri] int key)
{
return SingleResult.Create(db.EducationInfoes.Where(educationInfo => educationInfo.EducationID == key));
}
I want to overload this method in a such way that it might take 2 parameters [e.g. GetEducationInfo(int UserID, string EducationLevel)] and return only a single result based on the combination of two parameters (UserID and EducationLevel).
I have already tried to overload this method by following code...
// GET: odata/EducationInfoes(5, "bachelor")
[EnableQuery]
public SingleResult<EducationInfo> GetEducationInfo([FromODataUri] int key, string eLevel)
{
return SingleResult.Create(db.EducationInfoes.Where(educationInfo => educationInfo.UserID == key && educationInfo.EducationLevel == eLevel));
}
But when I'm sending GET requst to my WebService by this URL http://localhost:10194/odata/EducationInfoes(5, "Bachelor"), I'm getting this message:
No HTTP resource was found that matches the request URI 'http://localhost:10194/odata/EducationInfoes(5,"Bachelor")'.
If I change the default method to the following...
// GET: odata/EducationInfoes(5)
[EnableQuery]
public SingleResult<EducationInfo> GetEducationInfo([FromODataUri] int key)
{
return SingleResult.Create(db.EducationInfoes.Where(educationInfo => educationInfo.UserId== key));
}
and requesting using this url http://localhost:10194/odata/EducationInfoes(3) and getting this message
The action 'GetEducationInfo' on controller 'EducationInfoes' returned a SingleResult containing more than one element. SingleResult must have zero or one elements.
this message is returned because every single user has multiple Educational Information stored in EducationInfo table.
But I must have to get every EducationInfo result separately or as single result based on UserID and EducationLevel but not based on EducationID. Please help me...

Entity Framework shows inconsistent behaviour when used with Asp.net Identity

I have 3 tables Violation,Comment and and auto generated AspNetUsers respectively.The relationship between them as follows.
I am using code-first approach and my models are as follows.Some properties are removed for brevity.
Violation Model
public class Violation
{
public Violation()
{
this.Comments = new HashSet<Comment>();
}
public int Id { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
public virtual ApplicationUser CreatorUser { get; set; }
}
Comment Model
public class Comment
{
public int Id { get; set; }
[Required]
public string Content { get; set; }
[Required]
public DateTime PostedDateTime { get; set; }
public ApplicationUser ApplicationUser { get; set; }
public Violation Violation { get; set; }
}
ApplicationUser(AspNetUsers Table)
public class ApplicationUser : IdentityUser
{
public ApplicationUser()
{
this.Comments = new List<Comment>();
this.Violations = new List<Violation>();
}
public virtual List<Comment> Comments { get; set; }
public virtual List<Violation> Violations { get; set; }
}
The problem is that when I try to retrieve Comment's ApplicationUser navigation property , I see many of them pointing to a null property even database has proper record for each of them.
Shortly,EF doesn't retrieve database records properly.I stuck with it,can't find the reason.
In fact, it's not being lazy-loaded. You didn't add the virtual keyword to your Comment.ApplicationUser property, so Entity Framework cannot override it to add the lazy-loading logic. As a result, it's always going to be null unless you explicitly load it. Add the virtual keyword, and you'll be fine.
If you want the navigation properties populated you need to include them in the query:
var comments = context.Comments
.Include(c => c.Violation)
.Include(c => c.ApplicationUser)
.Where(x => x.Violation.Id == violationId);
https://msdn.microsoft.com/en-us/data/jj574232.aspx#eager

Resources