Cannot Scaffold (EF, Core 2.1) model that contains a 'bool' item - .net-core

My model looks like this:
namespace Flow.Models
{
public abstract class Project
{
public int ID { get; set; }
public String HashID { get; set; }
public string FileLoc { get; set; } //Use HashedID above.
public bool Network { get; set; }
public int ClientID { get; set; }
public int FirmID { get; set; }
public ICollection<Order> Orders { get; set; }
}
}
AND
namespace Flow.Models
{
public class ProjectDepo : Project
{
public DateTime DepoDate { get; set; } //some way to set this to only the date
public TimeSpan DepoTime { get; set; } //some way to set this to only the time of day
public bool DepoNoticeReceived { get; set; } //yes or no
//public int FirmUserID { get; set; }
}
}
When I scaffold ProjectDepo, I receive these types of error messages:
CS1061 'CreateModel' does not contain a definition for
'DepoNoticeReceived' and no extension method 'DepoNoticeReceived'
accepting a first argument of type 'CreateModel' could be found (are
you missing a using directive or an assembly reference?)
AND
CS1061 'CreateModel' does not contain a definition for 'Network' and
no extension method 'Network' accepting a first argument of type
'CreateModel' could be found (are you missing a using directive or an
assembly reference?)
Only for the fields that I have set a 'public bool'.
In the database, both 'Network' and 'DepoNoticeReceived' are set as 'bit'. One is nullable and the other is not.
I do not know why the Scaffolding generates these errors.
Please pass along any ideas.
thank you for any assistance.
chuck

Reading the other post indicated this is a bug in the Scaffolding. For some reason, bool values are NOT being properly referenced by scaffolding. Probably should be a bug for future releases of EF/Core. (This is still in EF/Core 2.1)
#Html.DisplayNameFor(model => model.Network)
(The above is the scaffolded code, which fails.)
#Html.DisplayNameFor(model => model.ProjectDepo.Network)
This is the correct code. It fills in the missing model 'ProjectDepo'.
(This find is due to the guidance of #Renato Alio. thank you for the guidance.)
chuck

Related

Entity Framework Core 2.2.1 DbQuery error system.Data.SqlTypes.SqlNullValueException

Trying to work with DbQuery. I need to get non-entity type UserDetailDTO using raw sql. Added DbQuery to the context and call it from controller. But it's generate system.Data.SqlTypes.SqlNullValueException.
My context:
public class TrainingAppDbContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbQuery<UserDetailDTO> UserDetailDTO { get; set; }
public TrainingAppDbContext(DbContextOptions<TrainingAppDbContext> options)
: base(options)
{
Database.EnsureCreated();
}
}
Controller:
public class AccountController : Controller
{
private readonly TrainingAppDbContext ct;
public AccountController(TrainingAppDbContext ct)
{
this.ct = ct;
}
public IActionResult Test()
{
var results = ct.UserDetailDTO.FromSql("SELECT * FROM users").ToList();
return View();
}
}
When I calling my UserDetailDTO from context it's generates an error.
error picture
Take a very close look at the UserDetailDTO class and any other classes that might have foreign keys to this table in your database. We recently found this error was being caused by a [Required] data annotation being added to our entities. In the example below, the [Required] attribute above FirstName is required and there should be no rows in your table where this column is null.
namespace Entities
{
public class UserDetailDTO
{
public int Id { get; set; }
[Required]
public string FirstName { get; set; }
public string LastName { get; set; }
public string PhoneNumber { get; set; }
public string EmailAddress { get; set; }
}
}
In previous versions of EF Core, the [Required] data annotation was ignored. Version 2.2.1 started looking for these annotations in your entities and enforcing them. We had no idea this was mistakenly added to some of our entities a few months back until we updated our EF Core version and started experiencing this error. Since the annotation was incorrectly added in our case, removing the annotation solved our problem. If you find this is the cause for your issue and you actually want the column to be required then you probably have data in your table where this column is null which is what's actually causing the error. Fix that bad data, make that column not null, and the query should start working again.
For those who have fields that can be nullable like DateTime, any Enums, make sure to keep it as a nullable field if your query returns null for those fields. Eg.
public DateTime? DateOfBirth { get; set; }

EF6 automatically includes nested objects

Probably a simple question, but there is something I can't get my head around.
My structure Bundle -> BundleMembers -> InsuranceTypes
When I retrieve a single record form BundleMembers, and I include Bundle. EF6 automatically includes all BundleMembers in the Bundle
Example:
public async Task<List<BundleMember>> GetBundleMembers(string userId, bool includeBundle, bool includeInsuranceTypes)
{
var bundleMembers = db.BundleMembers.Where(m => string.Equals(m.UserId, userId, StringComparison.CurrentCultureIgnoreCase));
if (includeBundle)
{
bundleMembers = bundleMembers.Include(o => o.Bundle);
}
if (includeInsuranceTypes)
{
bundleMembers = bundleMembers.Include(m => m.BundleMemberInsuranceType);
}
return await bundleMembers.ToListAsync();
}
I call the function like this:
GetBundleMembers(_userManager.GetUserId(User), true, false)
Do I have to access the data from Bundle, to avoid this?
EDIT 1:
My data model looks like this:
public class Bundle
{
public int BundleId { get; set; }
public State State { get; set; }
public ICollection<BundleMember> Members { get; set; }
public ICollection<InviteLink> InviteLinks { get; set; }
public string BundleName { get; set; }
public string Description { get; set; }
public string ImagePath { get; set; }
}
public enum State
{
NotApproved,
Approved,
Disabled,
Rejected
}
public class BundleMember
{
public ApplicationUser User { get; set; }
public string UserId { get; set; }
public int BundleMemberId { get; set; }
public int BundleId { get; set; }
public Bundle Bundle { get; set; }
public bool Admin { get; set; }
public int Price { get; set; }
public int Coverage { get; set; }
public ICollection<BundleMemberInsuranceType> BundleMemberInsuranceType { get; set; }
}
I did not include BundleMemberInsuranceType and InviteLink as they are working fine.
Relevant part of ApplicationDbContext:
public DbSet<Bundle> Bundles { get; set; }
public DbSet<BundleMember> BundleMembers { get; set; }
As suggested in comments:
The described behavior is actually expected. Since includeBundle is set to true, both Bundles and referenced BundleMembers are in the context, and relationship fixup will set all navigation properties according to the FK relationships.
Obviously, this works both from BundleMembers to Bundles and from Bundles to BundleMembers since .Include does nothing more than create the SQL statements to load the related entries into the context as well and relationship fixup will do the rest.
To have the Bundles not have BundleMembers, you'll have to load them without the BundleMembers in the context and set the navigation properties yourself (EF will always set both direct and inverse navigation properties). In order to do this, there are two main ways:
Either load your bundles in a fresh context without the previous loaded BundleMembers (best practice is to load them into memory since EF navigation properties are loaded due to eager loading; you could have entries attached to two contexts and an exception will be thrown) or
Detach your BundleMembers from the context before loading the Bundles into it.

Getting "Cannot insert the value NULL into column" when trying to save with .Add() method using DbContext . Please check my POCO's and save method

Used code first and everything appears to work apart from the below which also worked before when I used ObjectContext and called context.PCBuilds.AddObject(pcBuild) but after switching to DbContext it's giving me the error.
EFDbContext context = new EFDbContext();
public ActionResult Index()
{
PCBuild pcBuild = new PCBuild();
pcBuild.BuildID = 34245;
pcBuild.BuildName = "Test99";
pcBuild.MarkUp = 25;
pcBuild.BDetails = new List<BDetail>();
context.PCBuilds.Add(pcBuild);
//repository.PCBuilds.Attach(pcBuild);
context.SaveChanges();
return View();
}
Giving me the: Cannot insert the value NULL into column 'BuildID', table 'C:\USERS\ADMIN\DOCUMENTS\VISUAL STUDIO 2010\PROJECTS\NEOCART\NEOCART.WEBUI\APP_DATA\NEODBX.MDF.dbo.PCBuilds'; column does not allow nulls. INSERT fails. Where as BuildID was clearly set before the SaveChanges is called. Appears that calling the .Add(pcBuild) doesn't add the populated object for some reason and when savechanges is called it attempts to insert an empty PCBuild ?
Here are the POCO's
public class PCBuild
{
[Key]
public int BuildID { get; set; }
public string BuildName { get; set; }
public string Socket { get; set; }
public decimal? MarkUp {get; set;}
[InverseProperty("PCBuild")]
public virtual ICollection<BDetail> BDetails { get; set; }
}
public class BDetail
{
[Key]
public int LineID { get; set; }
[ForeignKey("PCBuild")]
public int BuildID { get; set; }
[ForeignKey("Product")]
public int ProductID { get; set; }
public bool? IsSelected { get; set; }
[InverseProperty("BDetails")]
public virtual PCBuild PCBuild { get; set; }
[InverseProperty("BDetails")]
public virtual Product Product { get; set; }
}
Use StoreGeneratedAttribute on the PCBuild.BuildID property. It is not only a key but IDENTITY field.
UPDATE
Actually, it should be [DatabaseGenerated(DatabaseGenerationOption.Identity)] annotation. The article linked above describes early CTP version.
UPDATE 2
Wait, the key is being generated by the app, it is not an identity column in database? Change annotation to [DatabaseGenerated(DatabaseGenerationOption.None)], re-create the context and rebuild the application.
I'm not really familiar with the Code First approach, but could it be that when you specify the BuildID as being a [Key] field, it is setting it as an auto identity field in the database?
As such it may be blocking your attempt to write to it.
Try removing the [Key] identifier, then recreate the database. Can you then save the object ok?

EF Code first Eager loading problem

I have two entities in 1:n relationship: Category and Product.
public class Category
{
public int CategoryID { get; set; }
public string CategoryName { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
public class Product
{
public int ProductID { get; set; }
public string ProductName { get; set; }
public virtual Product { get; set; }
}
public class context : DbContext
{
public DbSet<Category> Categories { get; set; }
public DbSet<Product> Products { get; set; }
}
I want to load products in every category by Eager loading.
context.Categories.Include(c=>c.Products)
but Include do not load any navigation property. it accept only one parameter called "path" typed string.
Are you missing a using? VS 2010 is a bit dumb on this one and you often have to explicitly put in:
using System.Data.Entity
..to get the lambda include option available.
It won't prompt you to add it as it already has a string based definition for Include available under
System.Linq
.Include(x => x.MyObject) is actually a new extension method for the existing linq method.

Which is the way to add MVC behavior to existing classes?

I have a Windows Form project that I would like to migrate toward a web application using ASP.NET MVC2.
In this project I have some POCO classes as in this example that are part of a class library and that I would like to use with a binary reference
public class Person
{
public int PersonID { get; set; }
public string Name { get; set; }
public DateTime BornDate { get; set; }
...
}
Is there a way to use these classes inside my Web MVC project and adding, for example validation attributes without modifying the original assembly?
thanks for helping
You may take a look at FluentValidation. It integrates nicely with ASP.NET MVC and allows you to unobtrusively add validation rules without modifying your POCO objects.
You can add Meta Information like Validation by using a Partial Class
namespace xxx.Data.yyy
{
[MetadataType(typeof(Posting_Validation))]
public partial class Posting {
}
public class Posting_Validation {
[Required(ErrorMessage = "Need title")]
[StringLength(50, ErrorMessage = "Must be under 50 characters")]
[DisplayName("Title")]
public string Title { get; set; }
[Display(AutoGenerateField = false)]
[HiddenInput(DisplayValue=false)]
public int PostingId { get; set; }
[UIHint("tiny_mce")]
public string HtmlContent { get; set; }
}
}

Resources