Fehler: Der Entitätstyp erfordert einen Primärschlüssel


71

Ich möchte die in diesem Thread gestellte Frage erweitern

Listenfeld an beobachtbare Sammlung binden

indem Sie ihm die Möglichkeit geben, die Daten dauerhaft zu speichern. Die Struktur ist größtenteils dieselbe, außer dass ich Entity Framework Core installiert und eine DbContextKlasse für die Datensätze erstellt habe. Ich habe eine Schaltfläche hinzugefügt, um das Dataset in SQL Server zu speichern. Der Kompilierungsfehler ist nicht aufgetreten, aber als ich versuchte, die Daten in der Datenbank zu speichern, wurde folgende Laufzeitausnahme angezeigt:

Nachricht = Für den Entitätstyp 'Frucht' muss ein Primärschlüssel definiert werden.

Die gesamte Ausnahme in ihrer Gesamtheit ist unten aufgeführt

System.InvalidOperationException wurde nicht behandelt
HResult = -2146233079
Message = Für den Entitätstyp 'Fruit' muss ein Primärschlüssel definiert werden.
Source = Microsoft.EntityFrameworkCore
Stacktrace:
bei Microsoft.EntityFrameworkCore.Internal.ModelValidator.ShowError (String message)
an Microsoft.EntityFrameworkCore.Internal.ModelValidator.EnsureNonNullPrimaryKeys (IModel Modell)
bei Microsoft.EntityFrameworkCore.Internal.ModelValidator.Validate (IModel Modell)
bei Microsoft.EntityFrameworkCore.Internal.RelationalModelValidator.Validate (IModel-Modell)
bei Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel (DbContext-Kontext, IConventionSetBuilder-KonventionSetBuilder, IModelValidator-Validator)
bei Microsoft.EntityFrameworkCore.Infrastructure.ModelSource. <> c__DisplayClass14_0.b__0 (Object k)
bei System.Collections.Concurrent.ConcurrentDictionary 2.GetOrAdd(TKey key, Func2 valueFactory)
bei Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel (DbContext Zusammenhang IConventionSetBuilder conventionSetBuilder, IModelValidator Validator)
bei Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel ()
bei Microsoft.EntityFrameworkCore.Internal.LazyRef 2.VisitCallSite (IServiceCallSite callSite, TArgument-Argument) bei Microsoft.Extensions.DependencyInjection.ServiceLit1.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


bei Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor 2.VisitCallSite (IServiceCallSite callSite, TArgument Argument) bei Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped (ScopedCallSite scopedCallSite, Serviceprovider - Provider ) bei Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor 1 Accessor) bei Microsoft.EntityFrameworkCore.ChangeTracking.ChangeTracker.get_StateManager () bei Microsoft.EntityFrameworkCore.ChangeTracking.ChangeTracker.DetectChanges () bei Microsoft.EntityFrameworkCore.DbContext.TryDetectChanges ()2.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.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




bei Microsoft.EntityFrameworkCore.DbContext.SaveChanges (Boolean acceptAllChangesOnSuccess)
bei Microsoft.EntityFrameworkCore.DbContext.SaveChanges ()
bei Fruits.MainWindow.SaveFruitCommandBinding_Executed (Objektabsender, ExecutedRoutedEventArgs e) in D: \ Frank \ Test \ Fruits \ Fruits \ MainWindow.xaml.cs: Zeile 50
bei SystemW. CommandBinding.OnExecuted (Objektabsender, ExecutedRoutedEventArgs e)
unter System.Windows.Input.CommandManager.ExecuteCommandBinding (Objektabsender, ExecutedRoutedEventArgs e, CommandBinding commandBinding)
unter System.Windows.Input.CommandManager.FindCommandBind, ICommand-Befehl, Boolean execute)
bei System.Windows.Input.CommandManager.FindCommandBinding (Objektabsender, RoutedEventArgs e, ICommand-Befehl, Boolean execute)
at System.Windows.Input.CommandManager.OnExecuted (Objektabsender, ExecutedRoutedEventArgs e) at System.Windows.UIElement.OnExecutedThunk (Objektabsender, ExecutedRoutedEventArgs e) at System.Windows.Input.ExecutedRoutedEventArgs.Inv System.Windows.RoutedEventArgs.InvokeHandler (Delegate-Handler, Objektziel) bei System.Windows.RoutedEventHandlerInfo.InvokeHandler (Objektziel, RoutedEventArgs routedEventArgs) bei System.Windows.EventRoute.InvokeHandlersImpl (Objektquelle) Windows.UIElement.RaiseEventImpl (DependencyObject-Absender, RoutedEventArgs-Argumente) bei System.Windows.UIElement.RaiseEvent (RoutedEventArgs-Argumente, Boolean Trusted) bei System.Windows.Input.RoutedCommand.ExecuteImpl (Objektparameter, IInputElement-Ziel, Boolean userInitiated) bei System.Windows.Input.RoutedCommand.ExecuteCore (Objektparameter, IInputElement-Ziel, Boolean userInitiated) bei MS.Internal.Commands.CommandHelecoreCommand , Boolean userInitiated) bei System.Windows.Controls.Primitives.ButtonBase.OnClick () bei System.Windows.Controls.Button.OnClick () bei System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp .UIElement.OnMouseLeftButtonUpThunk (Objektabsender, MouseButtonEventArgs e) bei System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler (Delegate genericHandler, Object genericTarget) bei System.Windows.RoutedEventArgs.InvokeHandler (Delegate-Handler, Objektziel) bei System.Windows.RoutedEventHandlerInfo.InvokeHandler (Objektziel, RoutedEventArgs routedEventArgs) bei System.Windows.EventRoute.InvokeHandlersImpl (Objektquelle, RoutedEventUgs. ReRaiseEventAs (DependencyObject-Absender, RoutedEventArgs-Argumente, RoutedEvent newEvent) bei System.Windows.UIElement.OnMouseUpThunk (Objektabsender, MouseButtonEventArgs e) bei System.Windows.Input.MouseButtonEventArgs.InvokeEventHindHand. InvokeHandler (Delegate-Handler, Objektziel) bei System.Windows.RoutedEventHandlerInfo.InvokeHandler (Objektziel,RoutedEventArgs routedEventArgs) bei System.Windows.EventRoute.InvokeHandlersImpl (Objektquelle, RoutedEventArgs-Argumente, Boolean reRaised) bei System.Windows.UIElement.RaiseEventImpl (DependencyObject-Absender, RoutedEventArgs-Argumente) .Windows.UIElement.RaiseEvent (RoutedEventArgs-Argumente, Boolean Trusted) bei System.Windows.Input.InputManager.ProcessStagingArea () bei System.Windows.Input.InputManager.ProcessInput (InputEventArgs-Eingabe) bei System.Windows.Input.InputPin InputReport inputReport) bei System.Windows.Interop.HwndMouseInputProvider.ReportInput (IntPtr hwnd, InputMode-Modus, Int32-Zeitstempel, RawMouseActions-Aktionen, Int32 x, Int32 y,Int32-Rad) bei System.Windows.Interop.HwndMouseInputProvider.FilterMessage (IntPtr hwnd, WindowMessage-Nachricht, IntPtr wParam, IntPtr lParam, Boolean & behandelt) bei System.Windows.Interop.HwndSource.InputFilPrtrPP lParam, Boolean & behandelt) bei MS.Win32.HwndWrapper.WndProc (IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean & behandelt) bei MS.Win32.HwndSubclass.DispatcherCallbackOperation (Object o )Thr.Wind. InternalRealCall (Rückruf delegieren, Objektargumente, Int32 numArgs) bei System.Windows.Threading.ExceptionWrapper.TryCatchWhen (Objektquelle, Rückruf delegieren, Objektargumente, Int32 numArgs, CatchHandler delegieren) bei System.Windows.Threading.Dispatcher.LegacyInvokeImpl (DispatcherPriority-Priorität, TimeSpan-Zeitlimit, Delegate-Methode, Objektargumente, Int32-Nummern) bei MS.Win32.HwndSubclass.SubclassWndProc (IntPtr hwnd, Int32-Nachricht, IntPtr wParam, IntPtr lParam) bei MS.WinMU. bei System.Windows.Threading.Dispatcher.PushFrameImpl (DispatcherFrame-Frame) bei System.Windows.Threading.Dispatcher.PushFrame (DispatcherFrame-Frame) bei System.Windows.Application.RunDispatcher (Objekt ignorieren) bei System.Windows.Application.RunInternal Fenster) bei System.Windows.Application.Run (Fensterfenster) bei System.Windows.Application.Run () bei Fruits.App.Main () bei System.AppDomain._nExecuteAssembly (RuntimeAssembly-Assembly,String [] Argumente) bei System.AppDomain.ExecuteAssembly (Zeichenfolge AssemblyFile, Evidence AssemblySecurity, String [] Argumente) bei Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly () bei System.Threading.ThreadHelper.ThreadStart_Context (Objektstatus) System. Threading.ExecutionContext.RunInternal (ExecutionContext ExecutionContext, ContextCallback-Rückruf, Objektstatus, Boolean PreserveSyncCtx) bei System.Threading.ExecutionContext.Run (ExecutionContext ExecutionContext, ContextCallback Callback, Objektstatus, Boolean PreserveSyncConxCon , ContextCallback-Rückruf, Objektstatus) bei System.Threading.ThreadHelper.ThreadStart () InnerException:ExecuteAssembly (String AssemblyFile, Evidence AssemblySecurity, String [] Argumente) bei Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly () bei System.Threading.ThreadHelper.ThreadStart_Context (Objektstatus) bei System.Threading.ExecutionContextContextContextContextContextContextContextContext Rückruf, Objektstatus, BooleanerveSyncCtx) bei System.Threading.ExecutionContext.Run (ExecutionContext ExecutionContext, ContextCallback-Rückruf, Objektstatus, Boolean PreserveSyncCtx) bei System.Threading.ExecutionContext.Run (ExecutionContext ExecutionContext, ContextCbacktext) Threading.ThreadHelper.ThreadStart () InnerException:ExecuteAssembly (String AssemblyFile, Evidence AssemblySecurity, String [] args) bei Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly () bei System.Threading.ThreadHelper.ThreadStart_Context (Objektstatus) bei System.Threading.ExecutionContextContextContextContextContextContextContext Rückruf, Objektstatus, BooleanerveSyncCtx) bei System.Threading.ExecutionContext.Run (ExecutionContext ExecutionContext, ContextCallback-Rückruf, Objektstatus, Boolean PreserveSyncCtx) bei System.Threading.ExecutionContext.Run (ExecutionContext ExecutionContext, ContextCbacktext) Threading.ThreadHelper.ThreadStart () InnerException:VisualStudio.HostingProcess.HostProc.RunUsersAssembly () bei System.Threading.ThreadHelper.ThreadStart_Context (Objektstatus) bei System.Threading.ExecutionContext.RunInternal (ExecutionContext ExecutionContext, ContextCallback-Rückruf, ObjectContext, ContextCallback-Rückruf (ExecutionContext executeContext, ContextCallback-Rückruf, Objektstatus, BooleanerveSyncCtx) bei System.Threading.ExecutionContext.Run (ExecutionContext-Ausführungskontext, ContextCallback-Rückruf, Objektstatus) bei System.Threading.ThreadHelper.ThreadStart () InnerException:VisualStudio.HostingProcess.HostProc.RunUsersAssembly () bei System.Threading.ThreadHelper.ThreadStart_Context (Objektstatus) bei System.Threading.ExecutionContext.RunInternal (ExecutionContext ExecutionContext, ContextCallback-Rückruf, ObjectContext, ContextCallback-Rückruf (ExecutionContext executeContext, ContextCallback-Rückruf, Objektstatus, BooleanerveSyncCtx) bei System.Threading.ExecutionContext.Run (ExecutionContext-Ausführungskontext, ContextCallback-Rückruf, Objektstatus) bei System.Threading.ThreadHelper.ThreadStart () InnerException:RunInternal (ExecutionContext Ausführungskontext, ContextCallback-Rückruf, Objektstatus, BooleanerveSyncCtx) bei System.Threading.ExecutionContext.Run (ExecutionContext ExecutionContext, ContextCallback-Rückruf, Objektstatus, Boolean PreserveSyncCtx) bei System.Threading.ContextConx Objektstatus) bei System.Threading.ThreadHelper.ThreadStart () InnerException:RunInternal (ExecutionContext Ausführungskontext, ContextCallback-Rückruf, Objektstatus, BooleanerveSyncCtx) bei System.Threading.ExecutionContext.Run (ExecutionContext ExecutionContext, ContextCallback-Rückruf, Objektstatus, Boolean PreserveSyncCtx) bei System.Threading.ContextConx Objektstatus) bei System.Threading.ThreadHelper.ThreadStart () InnerException:Objektstatus) bei System.Threading.ThreadHelper.ThreadStart () InnerException:Objektstatus) bei System.Threading.ThreadHelper.ThreadStart () InnerException:

Dies ist die aktualisierte Klasse Obst:

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

Das aktualisierte MainWindows xaml (um eine Schaltfläche zum Speichern hinzuzufügen)

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

und mein Code hinter den Hauptfenstern (Handler hinzugefügt)

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

Mein neu hinzugefügter 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");
        }
    }
}

Andere Klassen bleiben unverändert, aber ich habe sie trotzdem aufgelistet:

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

Die Struktur meines Projekts

Geben Sie hier die Bildbeschreibung ein

Meine Tabelle 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]

Bitte geben Sie an, warum in der Nachricht angegeben wurde, dass kein Primärschlüssel vorhanden war, solange dieser vorhanden ist


2
Diese Frage enthält viel zu viel Code, der für das Problem irrelevant ist.
Gert Arnold

Antworten:


129

Diese Ausnahmemeldung bedeutet nicht, dass ein Primärschlüssel in Ihrer Datenbank definiert werden muss , sondern dass ein Primärschlüssel in Ihrer Klasse definiert werden muss .

Obwohl Sie dies versucht haben:

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

Dies hat keine Auswirkung, da Entity Framework schreibgeschützte Eigenschaften ignoriert. Es muss: Wenn es einen FruitsDatensatz aus der Datenbank abruft , erstellt es ein FruitObjekt und ruft dann die Eigenschaftssetter für jede zugeordnete Eigenschaft auf. Das wird für schreibgeschützte Eigenschaften niemals funktionieren.

Sie benötigen Entity Framework, um den Wert von festlegen zu können ID. Dies bedeutet, dass die Eigenschaft einen Setter haben muss.


Das ist es!! Was Sie vorgeschlagen haben, hat den Fehler behoben. Aber können Sie vorschlagen, wie ich die Daten überbrücken soll, damit Daten von ObservableCollection <Fruit> an DbSet <Fruit> übergeben werden können? Gibt es einen besseren Weg, als die Zuordnung zu DbSet <Fruit> irgendwie durchzuführen?
user1205746

1
@ user1205746 DbSet<Fruit>.Localsollte eine sein, an die ObservableCollection<Fruit>Sie binden können. Es verfolgt alle in den Kontext geladenen Entitäten. Stellen Sie dann (oder vorher) einfach sicher, dass Sie die Entitäten in den Kontext laden ( context.Fruits.Load();) und es sollte funktionieren. Dies erfordert, dass Sie den Kontext mindestens so lange wie Ihr Ansichtsmodell beibehalten. Die Meinungen darüber, ob Kontexte kurzlebig oder langlebig sein sollten, gehen auseinander. Persönlich würde ich mich in diesem Fall für einen langlebigen Kontext entscheiden.

Ich glaube, ich habe Ihre Erklärung verstanden, kann aber Schwierigkeiten haben, die Implementierung herauszufinden, da ich sowohl neu bei wpf als auch bei entityframework bin. Könnten Sie mich bitte auf eine Literatur verweisen, in der die Schritte zum Binden aufgeführt sind?
user1205746

@ user1205746 Sorry, aber ich verstehe nicht gut genug, um etwas zu empfehlen. Sie wissen bereits, wie man sich an ein bindet ObservableCollection<Fruit>, nicht wahr? Sie tun dies in dem Code, den Sie in Ihrer Frage gezeigt haben. Alles, was Sie tun müssen, anstatt ein brandneues ObservableCollection<Fruit>Objekt zu erstellen, ist das, das EF für Sie erstellt.

Hinzufügen von [Schlüssel] war die Lösung
Andrew

23

Ich bin mit einem ähnlichen Fehler hierher gekommen:

System.InvalidOperationException: 'Für den Entitätstyp' MyType 'muss ein Primärschlüssel definiert werden.'

Nachdem ich die Antwort von hvd gelesen hatte, wurde mir klar, dass ich einfach vergessen hatte, mein Schlüsselobjekt "öffentlich" zu machen. Diese..

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

        // ...

Sollte das sein ..

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

        // ...

Wenn ein Modell basierend auf Ihrem C # -Objekt im Entitätsframework erstellt wird, müssen die Modellvariablen, die in der Datenbank
angezeigt

3

Ich habe eine etwas andere Fehlerursache gefunden. Anscheinend möchte SQLite den korrekten Eigenschaftsnamen der Primärschlüsselklasse verwenden. Damit...

Falscher PK-Name

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

Richtiger PK-Name

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

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

Es ist immer noch möglich, einen falschen PK-Namen zu verwenden, aber wir müssen das [Key] -Attribut wie verwenden

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

3

Ihre ID-Eigenschaft muss einen Setter haben. Der Setter kann jedoch privat sein. Das [Key]Attribut ist nicht erforderlich, wenn die Eigenschaft "Id" heißt, da sie über die Namenskonvention gefunden wird, bei der nach einem Schlüssel mit dem Namen "Id" gesucht wird.

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

1

Für den Entitätstyp 'DisplayFormatAttribute' muss ein Primärschlüssel definiert werden.

In meinem Fall stellte ich fest, dass das Problem darin bestand, dass ich Eigenschaften wie diese verwendete:

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

Ich bin mir nicht sicher, ob es einen besseren Weg gibt, es zu lösen, aber ich habe das Attribut Email und PhoneNumber in eine Zeichenfolge geändert. Problem gelöst.


1

Das hat bei mir funktioniert:

using System.ComponentModel.DataAnnotations;

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

0

Keine der Antworten funktionierte, bis ich die HasNoKey () -Methode aus der Entität entfernt habe. Vergessen Sie nicht, dies aus Ihrem Datenkontext zu entfernen, da sonst das Attribut [Schlüssel] nichts behebt.


0

Stellen Sie sicher, dass Sie die folgende Bedingung haben:

  1. Verwenden [key]Sie diese Option, wenn Ihr Primärschlüsselname nicht Idoder lautet ID.
  2. Verwenden Sie das publicSchlüsselwort.
  3. Der Primärschlüssel sollte Getter und Setter haben.

Beispiel:

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

0

Mit Scaffold-DbContext entfernt und wieder in die Tabelle eingefügt, und der Fehler wurde behoben


0

Als ich den Befehl Scaffold-DbContext verwendete, enthielt er weder die Annotation "[key]" in den Modelldateien noch den Eintrag "entity.HasKey (..)" in den Blöcken "modelBuilder.Entity". Meine Lösung bestand darin, in jedem "modelBuilder.Entity" -Block in der Datei * Context.cs eine Zeile wie diese einzufügen:

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

Ich sage nicht, dass dies besser oder sogar der richtige Weg ist. Ich sage nur, dass es bei mir funktioniert hat.


0

Ein weiterer Grund kann sein, dass Ihre Entitätsklasse mehrere Eigenschaften hat, die irgendwie benannt sind. Wenn Sie /.*id/ialso mit der ID-Groß- / Kleinschreibung ohne Berücksichtigung und ohne Elementartyp enden, gibt es kein [Key]Attribut.

EF wird nämlich versuchen, die PK selbst herauszufinden, indem nach elementaren typisierten Eigenschaften gesucht wird, die mit ID enden .

Siehe meinen Fall:

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

Fragen Sie nicht - Lecacy-Code. Das Idwurde sogar geerbt, so dass ich es nicht verwenden konnte [Key](nur den Code hier vereinfachen)

Aber hier ist EF total verwirrt.

Was geholfen hat, war die Verwendung von modelbuilder in der DBContext-Klasse.

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

Der Index für PK ist implizit.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.