How to extend table with a view in Entity framework - asp.net

I wanted to have a view to add a few extra proprieties and I tried the following:
Base table:
namespace Core.Model {
public class Item
{
[Key]
public int ItemId { get; set; }
[Required]
public ItemType Type { get; set; }
[Required]
[MaxLength(255)]
public string Name { get; set; }
//...
}
}
extended view:
namespace Core.Model
{
public class ItemExtended : Item
{
public int? CommentsCount { get; set; }
}
}
Then in the Context I have:
public DbSet<QuiverItemExtended> ItemsExtended { get; set; }
modelBuilder.Entity<ItemExtended>()
.ToTable("ItemsExtended")
.HasKey(view => new { view.ItemId });
This works for querying but when I try to insert a normal Item I get this exception:
All objects in the EntitySet 'Context.Items' must have unique primary
keys. However, an instance of type 'Core.Model.ItemExtended' and an
instance of type 'Core.Model.Item' both have the same primary key
value, 'EntitySet=Items;ItemId=1097'.
Any ideias how I can fix this?
thanks in advance

In this case I will solve this using a calculated column: http://www.davepaquette.com/archive/2012/09/23/calculated-columns-in-entity-framework-code-first-migrations.aspx

Related

.NET EF Inheritance without keys or constraints

It is possible to inherit from a type in dotnet EF without inherit the keys, indexes, etc?
I have these types:
public class Product : IEntity<long>
{
public long Id { get; set; }
public string Name { get; set; }
}
public class ProductVersion : Product
{
[Key]
public int ProductVersionId { get; set; }
public DateTime CreatedAt { get; set; }
}
I want ProductVersion to inherit all the properties from Product without creating any keys, constraints or navigation properties from the parent, just have the same properties and if are required or not, basically create a copy of the table columns.
The way you have it set up should remove the key constraint:
https://www.tektutorialshub.com/entity-framework-core/data-annotations-key-attribute-in-ef-core/
Adding [NotInherritedAttribute] should get rid of any of restraints you add:
https://learn.microsoft.com/en-us/dotnet/api/system.attributeusageattribute.inherited?view=net-6.0
[NotInheritedAttribute]
public class ProductVersion : Product{
[Key]
public int ProductVersionId { get; set; }
public DateTime CreatedAt { get; set; }
}

Why does a Required IdentityUser property result in a nullable database field?

I want to require that all entities of a particular type have a corresponding user in my ASP.NET MVC app, and that this is enforced at the database level i.e. as a non-nullable field. However, when I set the Required attribute on the IdentityUser property in my model class, like so:
using Microsoft.AspNetCore.Identity;
using System.ComponentModel.DataAnnotations;
namespace Test.Models
{
public class Foo
{
public int Id { get; set; }
[Required]
public IdentityUser User { get; set; }
}
}
the corresponding migration that gets generated sets the UserId table field to nullable:
UserId = table.Column<string>(type: "TEXT", nullable: true)
I've read that Table Per Hierarchy can cause this, but I'm not using any kind of inheritance.
What am I missing? Is there a way to achieve what I want?
Try to fix your class
public class Foo
{
[Key]
public int Id { get; set; }
[Required]
public string UserId { get; set; }
[ForeignKey(nameof(UserId))]
public IdentityUser User { get; set; }
}
Net 5 automatically creates a shadow property UserId in order you could save your Foo class. Since you used [Required], EF automatically added that it is nullable. If this property was not able to be null (for example if it was int type ( not int? ! )) you would not need a [Required] attribute.
Also what you can do is to use Fluent API to configure your contraints.
public class Foo
{
public int Id { get; set; }
public string UserId { get; set; }
public IdentityUser User { get; set; }
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public DbSet<Foo> Foos { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Foo>()
.HasRequired(c => c.User)
.WithMany(d => d.Foos)
.HasForeignKey(c => c.UserId);
}
}

How to fix ‘Cannot create a DbSet for 'DM_NCC_ThueSuat' because this type is not included in the model for the context’ error in C# ASP.NET

I have a code block regards get a list like that in aspnetzero:
public async Task<List<DMNCCThueSuatDto>> GetDSThueSuat()
{
using (_unitOfWorkManager.Current.SetTenantId(null))
{
var lstthueSuat = await _dmThueSuatRepository.Query(t => t.Where(i =>
i.IsDeleted == false)).OrderBy("thuesuat_ma asc").ToListAsync();
return ObjectMapper.Map<List<DMNCCThueSuatDto>>(lstthueSuat);
}
}
I expected a list of DMNCCThueSuatDto is returned but the error
Cannot create a DbSet for 'DM_NCC_ThueSuat' because this type is not
included in the model for the context.
is always displayed.
Also, i had myown a declaration
public virtual DbSet DS_ThueSuat { get; set; }
in my DBContext.
In my mariadb database, i had a table called "vs_dm_ncc_thuesuat"
and i have already declare a class for mapping to the table above
namespace VS.vHoaDon.Domains.DanhMuc.DMNhaCungCap
{
[Table("vs_dm_ncc_thuesuat")]
[MultiTenancySide(MultiTenancySides.Host)]
public class DM_NCC_ThueSuat : FullAuditedEntity
{
public int ThueSuat_Ma { get; set; }
public string ThueSuat_Ten { get; set; }
public int ThueSuat_GiaTri { get; set; }
public bool ThueSuat_HieuLuc { get; set; }
public DateTime? ThueSuat_BatDau { get; set; }
public DateTime? ThueSuat_KetThuc { get; set; }
}
}
I don't know why?
Any helps is appreciated.
Thank you so much.

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

Using ComplexType with ToList causes InvalidOperationException

I have this model
namespace ProjectTimer.Models
{
public class TimerContext : DbContext
{
public TimerContext()
: base("DefaultConnection")
{
}
public DbSet<Project> Projects { get; set; }
public DbSet<ProjectTimeSpan> TimeSpans { get; set; }
}
public class DomainBase
{
[Key]
public int Id { get; set; }
}
public class Project : DomainBase
{
public UserProfile User { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public IList<ProjectTimeSpan> TimeSpans { get; set; }
}
[ComplexType]
public class ProjectTimeSpan
{
public DateTime TimeStart { get; set; }
public DateTime TimeEnd { get; set; }
public bool Active { get; set; }
}
}
When I try to use this action I get the exception The type 'ProjectTimer.Models.ProjectTimeSpan' has already been configured as an entity type. It cannot be reconfigured as a complex type.
public ActionResult Index()
{
using (var db = new TimerContext())
{
return View(db.Projects.ToList);
}
}
The view is using the model #model IList<ProjectTimer.Models.Project>
Can any one shine some light as to why this would be happening?
Your IList<ProjectTimeSpan> property is not supported by EF. A complex type must always be part of another entity type, you cannot use a complex type by itself. If you absolutely need to have ProjectTimeSpan as a complex type, you will need to create a dummy entity type that only contains a key and a ProjectTimeSpan, and change the type of Project.TimeSpans to a list of that new type.

Resources