SaveChanges is not working in all my project?

2k views Asked by At

I working with a local database on an ASP.NET MVC project using Visual Studio.

I'm having trouble modifying the database. When I call SaveChanges() I always get this error:

The value cannot be null Parameter Name: Source

Here's an example of how I modify the database, and the error log / StackTrace.

 [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult CreateMedico(Medico medicoToCreate)
    {
        List<Medico> dedo = data.Medico.ToList();
        if (ModelState.IsValid)
        {
            using (MedsEntities data = new MedsEntities())
            {
                medicoToCreate.Id = dedo.Count() + 1;
                data.Medico.Add(medicoToCreate);
  System.Diagnostics.Debug.WriteLine("RECURSO :" + medicoToCreate.RECURSO_MEDICO);
                    System.Diagnostics.Debug.WriteLine("NOMBRE: " + medicoToCreate.NOMBRE);
                    System.Diagnostics.Debug.WriteLine("TIPO: " + medicoToCreate.TIPO);
                // and so on with all properties.....
                System.Diagnostics.Debug.WriteLine("MEDICO A GRABAR:" + medicoToCreate.NOMBRE);
                if (medicoToCreate == null)
                {
                    System.Diagnostics.Debug.WriteLine("MEDICOTOCREATE, IS NULL");

                }
                else {
                    System.Diagnostics.Debug.WriteLine("MEDICOTOCREATE, IS NOT NULL");
                }
                data.SaveChanges();
                return RedirectToAction("MedicosList");
            }
        }

        return RedirectToAction("MedicosList");
    }

Stack trace:

   en System.Data.Entity.Internal.InternalContext.SaveChanges()
   en System.Data.Entity.Internal.LazyInternalContext.SaveChanges()
   en System.Data.Entity.DbContext.SaveChanges()
   en FINAL.Controllers.HomeController.CreateMedico(Medico medicoToCreate) en d:\IDEX8544 KARLO\Documents\Visual Studio 2012\Projects\FINAL\FINAL\Controllers\HomeController.cs:línea 70
   en lambda_method(Closure , ControllerBase , Object[] )
   en System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
   en System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
   en System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   en System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass42.<BeginInvokeSynchronousActionMethod>b__41()
   en System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _)
   en System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.End()
   en System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult)
   en System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass37.<>c__DisplayClass39.<BeginInvokeActionMethodWithFilters>b__33()
   en System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49(

Connection Strings (Thanks Oleg):

 <connectionStrings>
    <add name="MedsEntities" connectionString="metadata=res://*/Models.ModelMeds.csdl|res://*/Models.ModelMeds.ssdl|res://*/Models.ModelMeds.msl;provider=System.Data.SqlServerCe.4.0;provider connection string=&quot;data source=|DataDirectory|\DB.sdf&quot;" providerName="System.Data.EntityClient" />
    <add name="HospitalEntities" connectionString="metadata=res://*/Models.ModelHosp.csdl|res://*/Models.ModelHosp.ssdl|res://*/Models.ModelHosp.msl;provider=System.Data.SqlServerCe.4.0;provider connection string=&quot;data source=|DataDirectory|\DB.sdf&quot;" providerName="System.Data.EntityClient" />
    <add name="LabsEntities" connectionString="metadata=res://*/Models.ModelLabs.csdl|res://*/Models.ModelLabs.ssdl|res://*/Models.ModelLabs.msl;provider=System.Data.SqlServerCe.4.0;provider connection string=&quot;data source=|DataDirectory|\DB.sdf&quot;" providerName="System.Data.EntityClient" />
    <add name="FarmaciasEntities" connectionString="metadata=res://*/Models.ModelFarms.csdl|res://*/Models.ModelFarms.ssdl|res://*/Models.ModelFarms.msl;provider=System.Data.SqlServerCe.4.0;provider connection string=&quot;data source=|DataDirectory|\DB.sdf&quot;" providerName="System.Data.EntityClient" />
  </connectionStrings>
</configuration>

MEDICO MODEL:

namespace FINAL.Models
{
    using System;
    using System.Collections.Generic;

    public partial class Medico
    {
        public string RECURSO_MEDICO { get; set; }
        public string NOMBRE { get; set; }
        public string TIPO { get; set; }
        public string TIPO2 { get; set; }
        public string TIPO3 { get; set; }
        public string CELULAR { get; set; }
        public string EMAIL { get; set; }
        public string TEL1 { get; set; }
        public string TEL2 { get; set; }
        public string EXT { get; set; }
        public string HOSPITAL { get; set; }
        public string DIRECCION { get; set; }
        public string LAT { get; set; }
        public string LON { get; set; }
        public string C33DIGITOS { get; set; }
        [Key]
        public int Id { get; set; }
    }
}

DB Model:

namespace FINAL.Models
{
    using System;
    using System.Data.Entity;
    using System.Data.Entity.Infrastructure;

    public partial class MedsEntities : DbContext
    {
        public MedsEntities()
            : base("name=MedsEntities")
        {
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            throw new UnintentionalCodeFirstException();
        }

        public DbSet<Medico> Medico { get; set; }
    }
}
3

There are 3 answers

2
Mairaj Ahmad On BEST ANSWER

You are getting this exception because some of your Model property has null value. But before checking this i would recommend you that you make a key column in your model and it shouldn't be Nullable. And when you add a new object of your model value of the key column should be set before calling SaveChanges.

You key column should be like this

[Key]
public int Id { get; set; }

If you don't want to manually set the value of this key column when adding a new object you can make it identity column so its value will be inserted automatically for this you have to add [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] to your key column.

[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }

And make sure when you add a new object all of your properties have the value otherwise you will get the same exception.

6
Dacker On

There is a variety of issues that will result in this errorMessage in EF.

As far as I remember is that Entity Framework relies on your object having some unique identifier. The easiest way to have one is the Id you have, but you shouldn't make it nullable. It should be of type int and your SQL Server should have identity set to true for this column.

If this is not your issue, debug and check which values are set and more important which are still null before SaveChanges is called.

2
ragerory On

Does it work if you remove your Bind(Exclude = "Id") attribute?

That appears to be the culprit. It looks like you're using it on a DomainModel instead of a ViewModel. You're trying to set it after the fact, but the attribute is already set.

There are a few ways around this.

  • Create a ViewModel that only has the properties you wish to be editable, and then pass that back and map to your DomainModel.

  • Let your database handle the auto increments

  • Simply remove the Bind(Exclude = "Id") attribute and don't expose that property (like above)

You're ultimately trying to insert without an Identifier.

You can see this answer here that has some more detail on it: Alternative for [Bind(Exclude = “Id”)]