【问题标题】:Error: the entity type requires a primary key错误:实体类型需要主键
【发布时间】:2017-09-16 03:17:50
【问题描述】:

我想扩展在此线程上提出的问题

Binding listbox to observablecollection

通过赋予它持久化数据的能力。结构基本相同,只是我安装了 Entity Framework Core,创建了一个 DbContext 类来保存记录。我添加了一个按钮来将数据集保存到 SQL Server。我没有遇到编译错误,但是当我尝试将数据保存在数据库中时,我得到了这个运行时异常:

Message=实体类型“水果”需要定义主键。

下面列出了整个异常

System.InvalidOperationException 未处理
HResult=-2146233079
Message=实体类型“水果”需要定义主键。
来源=Microsoft.EntityFrameworkCore
堆栈跟踪:
在 Microsoft.EntityFrameworkCore.Internal.ModelValidator.ShowError(字符串消息)
在 Microsoft.EntityFrameworkCore.Internal.ModelValidator.EnsureNonNullPrimaryKeys(IModel 模型)
在 Microsoft.EntityFrameworkCore.Internal.ModelValidator.Validate(IModel 模型)
在 Microsoft.EntityFrameworkCore.Internal.RelationalModelValidator.Validate(IModel 模型)
在 Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext 上下文,IConventionSetBuilder 约定集生成器,IModelValidator 验证器)
在 Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.c__DisplayClass14_0.b__0(对象 k)
在 System.Collections.Concurrent.ConcurrentDictionary2.GetOrAdd(TKey key, Func2 valueFactory)
在 Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext 上下文,IConventionSetBuilder 约定集生成器,IModelValidator 验证器)
在 Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel()
在 Microsoft.EntityFrameworkCore.Internal.LazyRef1.get_Value()
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServiceCollectionExtensions.<>c.<AddEntityFramework>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 参数)
在 Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite,ServiceProvider 提供程序)
在 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 参数)
在 Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite,ServiceProvider 提供程序)
在 Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.<>c__DisplayClass16_0.<RealizeService>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 访问者)
在 Microsoft.EntityFrameworkCore.ChangeTracking.ChangeTracker.get_StateManager()
在 Microsoft.EntityFrameworkCore.ChangeTracking.ChangeTracker.DetectChanges()
在 Microsoft.EntityFrameworkCore.DbContext.TryDetectChanges()
在 Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)
在 Microsoft.EntityFrameworkCore.DbContext.SaveChanges()
在 D:\Frank\Test\Fruits\Fruits\MainWindow.xaml.cs:line 50 中的 Fruits.MainWindow.SaveFruitCommandBinding_Executed(Object sender, ExecutedRoutedEventArgs e)
在 System.Windows.Input.CommandBinding.OnExecuted(对象发送者,ExecutedRoutedEventArgs e)
在 System.Windows.Input.CommandManager.ExecuteCommandBinding(对象发送者,ExecutedRoutedEventArgs e,CommandBinding commandBinding)
在 System.Windows.Input.CommandManager.FindCommandBinding(CommandBindingCollection commandBindings, Object sender, RoutedEventArgs e, ICommand command, Boolean execute)
在 System.Windows.Input.CommandManager.FindCommandBinding(对象发送者,RoutedEventArgs e,ICommand 命令,布尔执行)
在 System.Windows.Input.CommandManager.OnExecuted(对象发送者,ExecutedRoutedEventArgs e) 在 System.Windows.UIElement.OnExecutedThunk(对象发送者,ExecutedRoutedEventArgs e) 在 System.Windows.Input.ExecutedRoutedEventArgs.InvokeEventHandler(委托 genericHandler,对象目标) 在 System.Windows.RoutedEventArgs.InvokeHandler(委托处理程序,对象目标) 在 System.Windows.RoutedEventHandlerInfo.InvokeHandler(对象目标,RoutedEventArgs routedEventArgs) 在 System.Windows.EventRoute.InvokeHandlersImpl(对象源,RoutedEventArgs args,布尔 reRaised) 在 System.Windows.UIElement.RaiseEventImpl(DependencyObject 发件人,RoutedEventArgs 参数) 在 System.Windows.UIElement.RaiseEvent(RoutedEventArgs 参数,布尔值信任) 在 System.Windows.Input.RoutedCommand.ExecuteImpl(对象参数,IInputElement 目标,布尔用户启动) 在 System.Windows.Input.RoutedCommand.ExecuteCore(对象参数,IInputElement 目标,布尔用户启动) 在 MS.Internal.Commands.CommandHelpers.CriticalExecuteCommandSource(ICommandSource commandSource,Boolean userInitiated) 在 System.Windows.Controls.Primitives.ButtonBase.OnClick() 在 System.Windows.Controls.Button.OnClick() 在 System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e) 在 System.Windows.UIElement.OnMouseLeftButtonUpThunk(对象发送者,MouseButtonEventArgs e) 在 System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(委托 genericHandler,对象 genericTarget) 在 System.Windows.RoutedEventArgs.InvokeHandler(委托处理程序,对象目标) 在 System.Windows.RoutedEventHandlerInfo.InvokeHandler(对象目标,RoutedEventArgs routedEventArgs) 在 System.Windows.EventRoute.InvokeHandlersImpl(对象源,RoutedEventArgs args,布尔 reRaised) 在 System.Windows.UIElement.ReRaiseEventAs(DependencyObject 发件人,RoutedEventArgs 参数,RoutedEvent newEvent) 在 System.Windows.UIElement.OnMouseUpThunk(对象发送者,MouseButtonEventArgs e) 在 System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(委托 genericHandler,对象 genericTarget) 在 System.Windows.RoutedEventArgs.InvokeHandler(委托处理程序,对象目标) 在 System.Windows.RoutedEventHandlerInfo.InvokeHandler(对象目标,RoutedEventArgs routedEventArgs) 在 System.Windows.EventRoute.InvokeHandlersImpl(对象源,RoutedEventArgs args,布尔 reRaised) 在 System.Windows.UIElement.RaiseEventImpl(DependencyObject 发件人,RoutedEventArgs 参数) 在 System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs 参数) 在 System.Windows.UIElement.RaiseEvent(RoutedEventArgs 参数,布尔值信任) 在 System.Windows.Input.InputManager.ProcessStagingArea() 在 System.Windows.Input.InputManager.ProcessInput(InputEventArgs 输入) 在 System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport) 在 System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd,InputMode 模式,Int32 时间戳,RawMouseActions 动作,Int32 x,Int32 y,Int32 轮) 在 System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd,WindowMessage msg,IntPtr wParam,IntPtr lParam,布尔&处理) 在 System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd,Int32 msg,IntPtr wParam,IntPtr lParam,Boolean& 处理) 在 MS.Win32.HwndWrapper.WndProc(IntPtr hwnd,Int32 msg,IntPtr wParam,IntPtr lParam,Boolean& 处理) 在 MS.Win32.HwndSubclass.DispatcherCallbackOperation(对象 o) 在 System.Windows.Threading.ExceptionWrapper.InternalRealCall(委托回调,对象 args,Int32 numArgs) 在 System.Windows.Threading.ExceptionWrapper.TryCatchWhen(对象源,委托回调,对象 args,Int32 numArgs,委托 catchHandler) 在 System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority 优先级,TimeSpan 超时,委托方法,对象 args,Int32 numArgs) 在 MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd,Int32 msg,IntPtr wParam,IntPtr lParam) 在 MS.Win32.UnsafeNativeMethods.DispatchMessage(味精和味精) 在 System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame 框架) 在 System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame 框架) 在 System.Windows.Application.RunDispatcher(对象忽略) 在 System.Windows.Application.RunInternal(窗口窗口) 在 System.Windows.Application.Run(窗口窗口) 在 System.Windows.Application.Run() 在 Fruits.App.Main() 在 System.AppDomain._nExecuteAssembly(RuntimeAssembly 程序集,字符串 [] 参数) 在 System.AppDomain.ExecuteAssembly(字符串 assemblyFile,证据 assemblySecurity,String [] args) 在 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 在 System.Threading.ThreadHelper.ThreadStart_Context(对象状态) 在 System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext,ContextCallback 回调,对象状态,布尔值 preserveSyncCtx) 在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext,ContextCallback 回调,对象状态,布尔值 preserveSyncCtx) 在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext,ContextCallback 回调,对象状态) 在 System.Threading.ThreadHelper.ThreadStart() 内部异常:

这是更新后的水果类:

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
    }
}

更新后的 MainWindows xaml(添加保存按钮)

<Window x:Class="Fruits.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Fruits"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <RoutedCommand x:Key="AddFruit" />
        <RoutedCommand x:Key='SaveFruit' />
    </Window.Resources>
    <Window.CommandBindings>
        <CommandBinding Command='{StaticResource AddFruit}'
                                        Executed='AddFruitCommandBinding_Executed'
                                        CanExecute='AddFruitCommandBinding_CanExecute' />
        <CommandBinding Command='{StaticResource SaveFruit}'
                                        Executed='SaveFruitCommandBinding_Executed'
                                        CanExecute='SaveFruitCommandBinding_CanExecute' />
    </Window.CommandBindings>
    <Grid>
        <StackPanel Orientation='Vertical'
                                Margin='10'>
            <CheckBox IsChecked="{Binding ShowSelectedFruitOnly}">Selected Fruit Only</CheckBox>
            <ListBox x:Name='MyList'
                             ItemsSource="{Binding FruitsView}"
                             ItemTemplate='{StaticResource FruitTemp}' />
            <StackPanel Orientation="Horizontal"
                                    Margin="0,10,0,0">
                <Label Width="100">New Name:</Label>
                <TextBox Width="200"
                                 Text="{Binding NewFruitName, Mode=TwoWay }" 
                                 />
            </StackPanel>
            <StackPanel Orientation="Horizontal"
                                    Margin="0,10,0,0">
                <Label Width="100">New Color:</Label>
                <!--<TextBox Width="200"
                                 Text="{Binding NewFruitColor, UpdateSourceTrigger=PropertyChanged}" />-->
                <TextBox Width="200"
                                 Text="{Binding NewFruitColor, Mode=TwoWay }" />

                <ContentControl Style="{StaticResource ColorSwatch}"
                                                Margin="2"
                                                VerticalAlignment="Center"
                                                Content="{Binding NewFruitColor}" />
            </StackPanel>
            <StackPanel Orientation='Horizontal'>
            <Button x:Name='AddFruit'
                            Height='auto'
                            Width='auto'
                            Content='Add New Fruit 2'
                            Margin='0,10,0,0'
                            Command='{StaticResource AddFruit}' />
                <Button x:Name='SaveFruit'
                                Height='auto'
                                Width='auto'
                                Content='Save Fruit'
                                Margin='100,10,0,0'
                                Command='{StaticResource SaveFruit}' />
            </StackPanel>
        </StackPanel>
    </Grid>
</Window>

以及我在主窗口后面的代码(添加的处理程序)

using Fruits.ViewModels;
using System;
using System.Windows;
using System.Windows.Input;

namespace Fruits
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    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;
        }
    }
}

我新添加的dbContext:

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

其他类保持不变,但我还是列出了它们:

视图模型库

    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<Fruit>();

        }
        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<Fruit> _fruits;
        public ObservableCollection<Fruit> 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

<Application x:Class="Fruits.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:Fruits"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <Style x:Key="ColorSwatch"
                     TargetType="ContentControl">
            <Setter Property="Width"
                            Value="24" />
            <Setter Property="Height"
                            Value="24" />
            <Setter Property="IsTabStop"
                            Value="false" />
            <Setter Property="ContentTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <Rectangle HorizontalAlignment="Stretch"
                                             VerticalAlignment="Stretch"
                                             Stroke="Gray"
                                             StrokeThickness="1">
                            <Rectangle.Fill>
                                <SolidColorBrush Color="{Binding}" />
                            </Rectangle.Fill>
                        </Rectangle>
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <DataTemplate x:Key='FruitTemp'>
            <StackPanel Orientation='Horizontal'
                                    Margin='5'>
                <TextBlock x:Name='tbName'
                                     Text='{Binding FruitName}'
                                     Margin='10,0,0,0'
                                     Width='100' />
                <TextBlock x:Name='tbColor'
                                     Text='{Binding FruitColor}'
                                     Margin='10,0,0,0'
                                     Width='100' />
                <ContentControl Width="16"
                                                Height="16"
                                                Style="{StaticResource ColorSwatch}"
                                                Content="{Binding FruitColor}" />
                <!-- The problem here was you were trying to bind Checked, an event, 
                instead if IsChecked, a bool? property. 
                -->
                <CheckBox x:Name='cbSelected'
                                    Content='Selected'
                                    Margin='10,0,0,0'
                                    IsChecked='{Binding IsSelected}' />
            </StackPanel>
        </DataTemplate>
    </Application.Resources>
</Application>

我的项目结构

我在 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]

请说明为什么消息说没有主键而它确实存在

【问题讨论】:

  • 这个问题包含太多与问题无关的代码。

标签: c# wpf entity-framework-core


【解决方案1】:

此异常消息并不意味着它需要在您的数据库中定义一个主键,它意味着它需要在您的中定义一个主键。

虽然你已经尝试过这样做:

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

这没有效果,因为实体框架会忽略只读属性。它必须:当它从数据库中检索Fruits 记录时,它构造一个Fruit 对象,然后为每个映射属性调用属性设置器。这对只读属性永远不起作用。

您需要实体框架才能设置ID 的值。这意味着该属性需要有一个 setter。

【讨论】:

  • 就是这样!!您的建议修复了错误。但是您能否建议我将如何桥接数据,以便将来自 ObservableCollection 的数据传递给 DbSet?有没有比以某种方式分配给 DbSet 更好的方法?
  • @user1205746 DbSet&lt;Fruit&gt;.Local 应该是一个可以绑定的ObservableCollection&lt;Fruit&gt;。它跟踪加载到上下文中的所有实体。然后(或之前),只需确保将实体加载到上下文中(context.Fruits.Load();),它应该可以工作。这要求您将上下文至少与您的视图模型一样长。对于上下文应该是短命的还是长命的,意见不一。就个人而言,在这种情况下,我会选择长期存在的上下文。
  • 我想我理解了你的解释,但可能很难弄清楚实现,因为我是 wpf 和实体框架的新手。能否请您指出一些列出绑定它们的步骤的文献?
  • @user1205746 抱歉,我不太了解,无法推荐任何东西。您已经知道如何绑定到ObservableCollection&lt;Fruit&gt;,不是吗?您正在您的问题中显示的代码中执行此操作。因此,您需要做的就是使用 EF 为您创建的对象,而不是创建一个全新的 ObservableCollection&lt;Fruit&gt; 对象。
  • 添加 [Key] 是解决方案
【解决方案2】:

我带着类似的错误来到这里:

System.InvalidOperationException: '实体类型'MyType'需要定义一个主键。'

在阅读 hvd 的回答后,我意识到我只是忘记将我的密钥属性设为“公开”。这个..

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

        // ...

应该是这个..

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

        // ...

【讨论】:

  • 当基于实体框架中的 C# 对象创建模型时,将反映在数据库中的模型变量需要公开
【解决方案3】:

我发现了一些不同的错误原因。似乎 SQLite 想要使用正确的主键类属性名称。所以...

PK 名称错误

public class Client
{
  public int SomeFieldName { get; set; }  // It is the ID
  ...
}

正确的 PK 名称

public class Client
{
  public int Id { get; set; }  // It is the ID
  ...
}

public class Client
{
  public int ClientId { get; set; }  // It is the ID
  ...
}

仍然可能使用错误的 PK 名称,但我们必须使用 [Key] 属性,如

public class Client
{
   [Key]
   public int SomeFieldName { get; set; }  // It is the ID
   ...
}

【讨论】:

  • 顺便说一句,为了使这项工作自动进行,需要遵循的命名约定是命名属性 Id 或 Id。我有一种错误的印象,即任何带有 Id 后缀的列名都可以正常工作。但是,例如,Client_Id 将失败,而您的示例 (ClientId) 有效。更多信息:https://docs.microsoft.com/en-us/ef/core/modeling/keys
【解决方案4】:

这对我有用:

using System.ComponentModel.DataAnnotations;

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

【讨论】:

    【解决方案5】:

    确保您具备以下条件:

    1. 如果您的主键名称不是IdID,请使用[key]
    2. 使用public 关键字。
    3. 主键应该有 getter 和 setter。

    例子:

    public class MyEntity {
       [key]
       public Guid Id {get; set;}
    }
    

    【讨论】:

      【解决方案6】:

      您的 Id 属性需要有一个设置器。但是,setter 可以是私有的。 如果属性名为“Id”,则不需要[Key] 属性,因为它将通过命名约定找到它,在该约定中查找名称为“Id”的键。

      public Guid Id { get; }              // Will not work
      public Guid Id { get; set; }         // Will work
      public Guid Id { get; private set; } // Will also work
      

      【讨论】:

        【解决方案7】:

        当我使用 Scaffold-DbContext 命令时,它没有在模型文件中包含“[key]”注释,也没有在“modelBuilder.Entity”块中包含“entity.HasKey(..)”条目。我的解决方案是在 *Context.cs 文件的每个“modelBuilder.Entity”块中添加这样的一行:

        entity.HasKey(X => x.Id);
        

        我并不是说这更好,甚至不是正确的方法。我只是说它对我有用。

        【讨论】:

          【解决方案8】:

          另一个原因可能是您的实体类有几个名为 somhow /.*id/i 的属性 - 因此以 ID 不区分大小写和基本类型结尾并且没有 [Key] 属性。

          EF 将通过查找以 ID 结尾的基本类型属性来尝试自行找出 PK。

          看我的情况:

          public class MyTest, IMustHaveTenant
          {
            public long Id { get; set; }
            public int TenantId { get; set; }
            [MaxLength(32)]
            public virtual string Signum{ get; set; }
            public virtual string ID { get; set; }
            public virtual string ID_Other { get; set; }
          }
          

          别问 - 遗留代码。 Id 甚至被继承了,所以我不能使用[Key](这里只是简化代码)

          但这里的 EF 完全糊涂了。

          在 DBContext 类中使用 modelbuilder this 有帮助。

                      modelBuilder.Entity<MyTest>(f =>
                      {
                          f.HasKey(e => e.Id);
                          f.HasIndex(e => new { e.TenantId });
                          f.HasIndex(e => new { e.TenantId, e.ID_Other });
                      });
          

          PK 上的索引是隐含的。

          【讨论】:

            【解决方案9】:

            如果出现错误:

            实体类型“DeviceFlowCodes”需要一个主键 定义。如果您打算使用无密钥实体类型,请调用“HasNoKey” 在“OnModelCreating”中。有关无密钥实体类型的更多信息, 见https://go.microsoft.com/fwlink/?linkid=2141943

            您可能正在使用带有个人用户帐户的解决方案,并且在ApplicationDbContext 中使用过protected override void OnModelCreating(ModelBuilder modelBuilder)

            错误来自具有public DbSet&lt;DeviceFlowCodes&gt; DeviceFlowCodes { get; set; }ApiAuthorizationDbContext

            通过在protected override void OnModelCreating 中调用base.OnModelCreating(modelBuilder); 来解决错误。

            来源:

            https://github.com/IdentityServer/IdentityServer4/issues/3169

            【讨论】:

              【解决方案10】:

              我碰巧什么都试过了:

              • 确保该属性有一个设置器
              • 尝试使用[Key] 注释
              • 使用了一个名为“Id”的属性,带有和不带有[Key] 注释。

              这些都不起作用,原因很简单:我的数据库不可用。

              修复与数据库的连接解决了“需要主键”问题。

              (奇怪的是即使在这种情况下也会显示这个错误。)

              【讨论】:

                【解决方案11】:

                实体类型“DisplayFormatAttribute”需要一个主键 已定义。

                就我而言,我发现问题在于我使用了这样的属性:

                public string LastName { get; set; }  //OK
                public string Address { get; set; }   //OK 
                public string State { get; set; }     //OK
                public int? Zip { get; set; }         //OK
                public EmailAddressAttribute Email { get; set; } // NOT OK
                public PhoneAttribute PhoneNumber { get; set; }  // NOT OK
                

                不确定是否有更好的解决方法,但我将电子邮件和电话号码属性更改为字符串。问题解决了。

                【讨论】:

                  【解决方案12】:

                  在我从实体中删除 HasNoKey() 方法之前,没有任何答案有效。不要忘记从您的数据上下文中删除它,否则 [Key] 属性将无法解决任何问题。

                  【讨论】:

                    【解决方案13】:

                    使用 Scaffold-DbContext 删除并重新添加到表中,错误消失了

                    【讨论】:

                      【解决方案14】:

                      在 DBContext 我有这个 &lt;List&gt; 导致错误的代码:

                          public DbSet<List<<Item>> Items { get; set; } = null!;
                      

                      你可以通过创建另一个类来解决它,我创建了一个类ListItem,其中包含一个List&lt;Item&gt;,然后声明两者:

                          public DbSet<Item> Items { get; set; } = null!;
                      
                      
                          public DbSet<ListItem> ListItems { get; set; } = null!;
                      

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 2022-11-30
                        • 1970-01-01
                        • 2022-06-16
                        • 2021-07-23
                        • 2021-11-27
                        • 2018-08-13
                        • 2019-09-13
                        • 1970-01-01
                        相关资源
                        最近更新 更多