Error: the entity type requires a primary key

匿名 (未验证) 提交于 2019-12-03 01:27:01

问题:

I would like to expand the question asked on this thread

Binding listbox to observablecollection

by giving it an ability to persistent the data. The structure is mostly the same except I installed Entity Framework Core, created a DbContext class to hold the records. I added a button to save the dataset to SQL Server. I did not encounter the compiling error but when I attempted to save the data in the database I got this run time exception:

Message=The entity type 'Fruit' requires a primary key to be defined.

The whole exception in its entirety is listed below

System.InvalidOperationException was unhandled
HResult=-2146233079
Message=The entity type 'Fruit' requires a primary key to be defined.
Source=Microsoft.EntityFrameworkCore
StackTrace:
at Microsoft.EntityFrameworkCore.Internal.ModelValidator.ShowError(String message)
at Microsoft.EntityFrameworkCore.Internal.ModelValidator.EnsureNonNullPrimaryKeys(IModel model)
at Microsoft.EntityFrameworkCore.Internal.ModelValidator.Validate(IModel model)
at Microsoft.EntityFrameworkCore.Internal.RelationalModelValidator.Validate(IModel model)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext context, IConventionSetBuilder conventionSetBuilder, IModelValidator validator)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.c__DisplayClass14_0.b__0(Object k)
at System.Collections.Concurrent.ConcurrentDictionary2.GetOrAdd(TKey key, Func2 valueFactory)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext context, IConventionSetBuilder conventionSetBuilder, IModelValidator validator)
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel()
at Microsoft.EntityFrameworkCore.Internal.LazyRef1.get_Value()
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServiceCollectionExtensions.c.b__0_6(IServiceProvider p)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactoryService(FactoryService factoryService, ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor
2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor
2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.c__DisplayClass16_0.b__0(ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider)
at Microsoft.EntityFrameworkCore.Infrastructure.AccessorExtensions.GetService[TService](IInfrastructure
1 accessor)
at Microsoft.EntityFrameworkCore.ChangeTracking.ChangeTracker.get_StateManager()
at Microsoft.EntityFrameworkCore.ChangeTracking.ChangeTracker.DetectChanges()
at Microsoft.EntityFrameworkCore.DbContext.TryDetectChanges()
at Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.DbContext.SaveChanges()
at Fruits.MainWindow.SaveFruitCommandBinding_Executed(Object sender, ExecutedRoutedEventArgs e) in D:\Frank\Test\Fruits\Fruits\MainWindow.xaml.cs:line 50
at System.Windows.Input.CommandBinding.OnExecuted(Object sender, ExecutedRoutedEventArgs e)
at System.Windows.Input.CommandManager.ExecuteCommandBinding(Object sender, ExecutedRoutedEventArgs e, CommandBinding commandBinding)
at System.Windows.Input.CommandManager.FindCommandBinding(CommandBindingCollection commandBindings, Object sender, RoutedEventArgs e, ICommand command, Boolean execute)
at System.Windows.Input.CommandManager.FindCommandBinding(Object sender, RoutedEventArgs e, ICommand command, Boolean execute)
at System.Windows.Input.CommandManager.OnExecuted(Object sender, ExecutedRoutedEventArgs e) at System.Windows.UIElement.OnExecutedThunk(Object sender, ExecutedRoutedEventArgs e) at System.Windows.Input.ExecutedRoutedEventArgs.InvokeEventHandler(Delegate genericHandler, Object target) at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target) at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs) at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised) at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args) at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted) at System.Windows.Input.RoutedCommand.ExecuteImpl(Object parameter, IInputElement target, Boolean userInitiated) at System.Windows.Input.RoutedCommand.ExecuteCore(Object parameter, IInputElement target, Boolean userInitiated) at MS.Internal.Commands.CommandHelpers.CriticalExecuteCommandSource(ICommandSource commandSource, Boolean userInitiated) at System.Windows.Controls.Primitives.ButtonBase.OnClick() at System.Windows.Controls.Button.OnClick() at System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e) at System.Windows.UIElement.OnMouseLeftButtonUpThunk(Object sender, MouseButtonEventArgs e) at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget) at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target) at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs) at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised) at System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender, RoutedEventArgs args, RoutedEvent newEvent) at System.Windows.UIElement.OnMouseUpThunk(Object sender, MouseButtonEventArgs e) at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget) at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target) at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs) at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised) at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args) at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args) at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted) at System.Windows.Input.InputManager.ProcessStagingArea() at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input) at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport) at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel) at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled) at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler) at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs) at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam) at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg) at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame) at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame) at System.Windows.Application.RunDispatcher(Object ignore) at System.Windows.Application.RunInternal(Window window) at System.Windows.Application.Run(Window window) at System.Windows.Application.Run() at Fruits.App.Main() at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart() InnerException:

This is the updated class Fruit:

namespace Fruits.ViewModels {     [Table("Fruits")]     public  class Fruit : ViewModelBase     {         #region Constractor         public Fruit()         {         }         public Fruit(string name, String clrString)         {             FruitName = name;             //  Parse colors like so: (Color)ColorConverter.ConvertFromString(clrString);             FruitColor = clrString;             _id = Guid.NewGuid();         }         public Fruit(string name, Color clr)         {             FruitName = name;             FruitColor = clr.ToString();             _id = Guid.NewGuid();         }          #endregion          #region Properties         private Guid _id;         [Key]         public Guid ID         {             get { return _id; }         }          #region FruitName         private string _fruitname;         public string FruitName         {             get             {                 return _fruitname;             }             set             {                 if (_fruitname != value)                 {                     _fruitname = value;                     OnPropertyChanged("FruitName");                 }             }         }         #endregion          #region FruitColor         private String _fruitcolor;         public String FruitColor         {             get             {                 return _fruitcolor;             }             set             {                 if (_fruitcolor != value)                 {                     _fruitcolor = value;                     OnPropertyChanged("FruitColor");                 }             }         }         #endregion          #region Selected Property         private bool _isSelected = true;         //  NOTE: I renamed this property         public bool IsSelected         {             get             {                 return _isSelected;             }             set             {                 if (_isSelected != value)                 {                     _isSelected = value;                     OnPropertyChanged("IsSelected");                 }             }         }         #endregion          #endregion     } }

The updated MainWindows xaml (to add a save button)

Selected Fruit Only                                                                                 

and my code behind the mainwindows (added handler)

using Fruits.ViewModels; using System; using System.Windows; using System.Windows.Input;  namespace Fruits {     ///      /// Interaction logic for MainWindow.xaml     ///      public partial class MainWindow : Window     {         public MainWindow()         {             InitializeComponent();             DataContext = new MainViewModel();              ViewModel.AddNewFruit("Jackfruit", "Yellow");             ViewModel.AddNewFruit("Watermelon", "ForestGreen");             ViewModel.AddNewFruit("Apple", "Red");             ViewModel.AddNewFruit("Banana", "Yellow");             ViewModel.AddNewFruit("Orange", "DeepSkyBlue");              //ViewModel.Fruits[0].IsSelected = false;             //ViewModel.Fruits[1].IsSelected = false;              ViewModel.FruitsView.Refresh();         }          public MainViewModel ViewModel { get { return DataContext as MainViewModel; } }          private void AddFruitCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)         {             ViewModel.AddNewFruit();         }          private void AddFruitCommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)         {             e.CanExecute =                     ViewModel != null                     && !String.IsNullOrWhiteSpace(ViewModel.NewFruitName)                     && !String.IsNullOrWhiteSpace(ViewModel.NewFruitColor)                     ;         }          private void SaveFruitCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)         {             using (var db=new FruitDbContext())             {                 db.SaveChanges();             }         }          private void SaveFruitCommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)         {             e.CanExecute = true;         }     } }

My newly added dbContext:

namespace Fruits.ViewModels {     public class FruitDbContext:DbContext     {         public DbSet Fruits { get; set; }         protected override void OnConfiguring(DbContextOptionsBuilder optionBuilder)         {             optionBuilder.UseSqlServer(@"Server = xxx; Database=Test; Integrated Security = True");         }     } }

Other classes remain unchanged, but I listed them anyway:

ViewModelBase

    namespace Fruits.ViewModels     {         public  class ViewModelBase : INotifyPropertyChanged         {             public event PropertyChangedEventHandler PropertyChanged;             public void OnPropertyChanged(string name)             {                 if (PropertyChanged != null)                 {                     PropertyChanged(this, new PropertyChangedEventArgs(name));                 }             }         }     }  ViewModel  using System; using System.Collections.ObjectModel; using System.ComponentModel; using System.Windows.Data; using System.Windows.Media;  namespace Fruits.ViewModels {      #region MainViewModel Class     public class MainViewModel : ViewModelBase     {         public  MainViewModel()         {             Fruits = new ObservableCollection();          }         public ICollectionView FruitsView { get; private set; }          #region ShowSelectedFruitOnly Property         private bool _showSelectedFruitOnly = true;         public bool ShowSelectedFruitOnly         {             get { return _showSelectedFruitOnly; }             set             {                 if (value != _showSelectedFruitOnly)                 {                     _showSelectedFruitOnly = value;                     FruitsView.Refresh();                     OnPropertyChanged("ShowSelectedFruitOnly");                 }             }         }         #endregion ShowSelectedFruitOnly Property          #region Add Methods         public void AddNewFruit()         {             Fruits.Add(new Fruit(NewFruitName, NewFruitColor));              NewFruitName = "";             NewFruitColor = "";         }         public void AddNewFruit(string name, string color)         {             Fruits.Add(new Fruit(name, color));         }         public void AddNewFruit(string name, Color color)         {             Fruits.Add(new Fruit(name, color));         }         #endregion Add Methods          #region NewFruitName Property         private String _newFruitName = default(String);         public String NewFruitName         {             get { return _newFruitName; }             set             {                 if (value != _newFruitName)                 {                     _newFruitName = value;                     OnPropertyChanged("NewFruitName");                 }             }         }         #endregion NewFruitName Property          #region NewFruitColor Property         private String _newFruitColor = default(String);         public String NewFruitColor         {             get { return _newFruitColor; }             set             {                 if (value != _newFruitColor)                 {                     _newFruitColor = value;                     OnPropertyChanged("NewFruitColor");                 }             }         }         #endregion NewFruitColor Property          #region Fruits Property         private static ObservableCollection _fruits;         public ObservableCollection Fruits         {             get { return _fruits; }             private set             {                 if (value != _fruits)                 {                     _fruits = value;                      FruitsView = CollectionViewSource.GetDefaultView(Fruits);                      FruitsView.Filter = FruitFilterPredicate;                     FruitsView.Refresh();                      OnPropertyChanged("Fruits");                 }             }         }         protected bool FruitFilterPredicate(Object o)         {             if (ShowSelectedFruitOnly)             {                 return (o as Fruit).IsSelected;             }              return true;         }         #endregion Fruits Property     }      #endregion MainViewModel Class }

App.xaml

The structure of my project

My table in SQL Server:

CREATE TABLE [dbo].[Fruits] (     [ID] [uniqueidentifier] NOT NULL,     [FruitName] [nvarchar](50) NULL,     [FruitColor] [nvarchar](50) NULL,     [IsSelected] [nvarchar](1) NULL,       CONSTRAINT [PK_Fruit]          PRIMARY KEY CLUSTERED ([ID] ASC)                     WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,                            IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,                            ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY]

Please advise why the message said there was no primary key while it does exist

回答1:

This exception message doesn't mean it requires a primary key to be defined in your database, it means it requires a primary key to be defined in your class.

Although you've attempted to do so:

private Guid _id; [Key] public Guid ID {     get { return _id; } }

This has no effect, as Entity Framework ignores read-only properties. It has to: when it retrieves a Fruits record from the database, it constructs a Fruit object, and then calls the property setters for each mapped property. That's never going to work for read-only properties.

You need Entity Framework to be able to set the value of ID. This means the property needs to have a setter.



回答2:

I came here with similar error:

System.InvalidOperationException: 'The entity type 'MyType' requires a primary key to be defined.'

After reading answer by hvd, realized I had simply forgotten to make my key property 'public'. This..

namespace MyApp.Models.Schedule {     public class MyType     {         [Key]         int Id { get; set; }          // ...

Should be this..

namespace MyApp.Models.Schedule {     public class MyType     {         [Key]         public int Id { get; set; }  // must be public!          // ...


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!