Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The required column 'CustomerId' was not present in the results of a 'FromSql' operation

The error message is clear:

'The required column 'CustomerId' was not present in the results of a 'FromSql' operation'

But somehow I didn't really expect a CustomerId?

The error happens here:

contacts = db.Contacts.FromSql("SIP_API_MONDIA_Contacts_sel").ToList();
addresses = db.Addresses.FromSql("SIP_API_MONDIA_Address_sel").ToList();

Controller:

  public IList<Customer> GetAllCustomers()
        {
            //Initialize the objects
            IList<Customer> customers = null;
            IList<Contacts> contacts = null;
            IList<Addresses> addresses = null;

            //Fetch the data from stored procedures
            customers = db.Customers.FromSql("SomeProcName").ToList();
            contacts = db.Contacts.FromSql("SomeProcName").ToList();
            addresses = db.Addresses.FromSql("SomeProcName").ToList();

            //Loop through customers and add the contact and addresses when required
            foreach(var item in customers)
            {
                item.Contacts = contacts.Where(x => x.Customer == item.Id).ToList();
                item.Addresses = addresses.Where(x => x.Customer == item.Id).ToList();
            }
            return customers;
        }

The model:

public class Customer
    {
        public Guid Id { get; set; }
        public string Code { get; set; }
        public string Name { get; set; }
        public string VatCode { get; set; }
        public string ChamberOfCommerceCode { get; set; }
        public DateTime Modified { get; set; }
        public DateTime Created { get; set; }
        public string LanguageCode { get; set; }
        public decimal Discount { get; set; }
        public string CustomerManager { get; set; }
        public Guid PriceList { get; set; }
        public Guid PaymentCondition { get; set; }
       // public bool VatLiable { get; set; }
        public bool IsBlocked { get; set; }
        public bool IsProspect { get; set; }
        public bool IsSuspect { get; set; }
        public string Website { get; set; }
        public string DashboardUrl { get; set; }
        public string Email { get; set; }
        public string Phone { get; set; }
        public string Fax { get; set; }
        //     public ICollection<FreeFields> FreeFields { get; set; }
        //      public Dictionary<string, string> UknownElements { get; set; }
        public ICollection<Contacts> Contacts { get; set; }
        public ICollection<Addresses> Addresses { get; set; }
    }

    public class FreeFields
    {
        public string Key { get; set; }
        public string Value { get; set; }
    }

    public class Contacts
    {
        public Guid Id { get; set; }
        public string FirstName { get; set; }
        public string MiddleName { get; set; }
        public string LastName { get; set; }
        public string Initials { get; set; }
        public string Function { get; set; }    
        public Guid Customer { get; set; }
        public string Email { get; set; }
        public string Phone { get; set; }
        public string Mobile { get; set; }
        public string LanguageCode { get; set; }
        public bool IsMainContact { get; set; }
        public string Gender { get; set; }
        public string Username { get; set; }
    }
    public class Addresses
    {
        public Guid Id { get; set; }
        public string AddressLine1 { get; set; }
        public string AddressLine2 { get; set; }
        public string AddressLine3 { get; set; }
        public string Postcode { get; set; }
        public string City { get; set; }
        public string Country { get; set; }
        public string CountryCode { get; set; }
        public string Type { get; set; }
        public Guid Customer { get; set; }// This Property should be GUID instead of String..
        public bool IsMainAddress { get; set; }
        public string Route { get; set; }
        public string State { get; set; }
    }

I am not entirely sure what the error means with 'CustomerId' The stored procedures return the 100% exact value of the models.

Edit in order to add print scrn of the sql resultset && DbContext:

public class IsahContext : DbContext
    {
        public  IsahContext()
        {

        }

        public IsahContext(DbContextOptions<IsahContext> options)
            : base(options)
        {
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                optionsBuilder.UseSqlServer(Setting.ConnectionString);
            }
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
        }

        //Entities will come here 
        public DbSet<Customer> Customers { get; set; }
        public DbSet<Addresses> Addresses { get; set; }
        public DbSet<Contacts> Contacts { get; set; }

    }

enter image description here

enter image description here

like image 238
Falcon Avatar asked Feb 26 '19 15:02

Falcon


1 Answers

CustomerId is the conventional name for the Foreign Key of the one-to-many relationships introduced by the

public ICollection<Contacts> Contacts { get; set; }
public ICollection<Addresses> Addresses { get; set; }

collection navigation properties of the Customer class.

Although the related classes Contacts and Addresses contain a property Guid Customer, due to its name it's not recognized as a Foreign Key, so it falls into No Foreign Key Property category. And EF Core assumes a shadow property (and column) named CustomerId. Shadow property convention explanation is:

Shadow properties can be created by convention when a relationship is discovered but no foreign key property is found in the dependent entity class. In this case, a shadow foreign key property will be introduced. The shadow foreign key property will be named <navigation property name><principal key property name> (the navigation on the dependent entity, which points to the principal entity, is used for the naming). If the principal key property name includes the name of the navigation property, then the name will just be <principal key property name>. If there is no navigation property on the dependent entity, then the principal type name is used in its place.

In order to map the Customer property as a FK, you should use either ForeignKey attribute:

You can use the Data Annotations to configure which property should be used as the foreign key property for a given relationship. This is typically done when the foreign key property is not discovered by convention.

Tip
The [ForeignKey] annotation can be placed on either navigation property in the relationship. It does not need to go on the navigation property in the dependent entity class.

e.g. (since you have no navigation property in the dependent entities):

[ForeignKey(nameof(Contacts.Customer))]
public ICollection<Contacts> Contacts { get; set; }

[ForeignKey(nameof(Addresses.Customer))]
public ICollection<Addresses> Addresses { get; set; }

or Fluent API:

modelBuilder.Entity<Customer>()
    .HasMany(customer => customer.Contacts)
    .WithOne() // no nav property
    .HasForeignKey(contact => contact.Customer); // the FK property

modelBuilder.Entity<Customer>()
    .HasMany(customer => customer.Addresses)
    .WithOne() // no nav property
    .HasForeignKey(address => address.Customer); // the FK property
like image 122
Ivan Stoev Avatar answered Sep 26 '22 08:09

Ivan Stoev