トピックのタイトルで述べたように、DataContext.SubmitChanges() メソッドに問題があります。ユーザーと管理者(および医師などの他の役割ですが、現在これら2つのテーブルで作業しています)の2つのテーブルがあります。これら 2 つのテーブルの SQL スクリプト: ユーザー:
`CREATE TABLE [dbo].[Users](
[usrId] [int] IDENTITY(1,1) NOT NULL,
[login] [nvarchar](50) NOT NULL,
[password] [nvarchar](50) NOT NULL,
[role] [char](3) NOT NULL,
[staffId] [int] NOT NULL,
CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED
(
[usrId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]`
管理者向け:
`CREATE TABLE [dbo].[Administrators](
[adminId] [int] IDENTITY(1,1) NOT NULL,
[name] [nvarchar](50) NOT NULL,
[surname] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_Administrators] PRIMARY KEY CLUSTERED
(
[adminId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]`
これで、管理者は Administrators.adminId = Users.staffId (adminId は PK、staffId は FK) でユーザーに参加します。簡単に言えば、User.staffId == Administrator.adminId AND User.role = "ADM" の場合、テーブル Users の User が管理者であることを知っています。
では、問題はどこにあるのでしょうか。このデータベースの LINQ マッピングを作成しました。
[Database(Name = "BD_PROJ_GKiO3")]
public class BD_PROJ_GKiO3 : DataContext
{
public Table<User> Users;
public Table<Doctor> Doctors;
public Table<LaboratoryWorker> LaboratoryWorkers;
public Table<LaboratoryManager> LaboratoryManagers;
public Table<Registrator> Registrators;
public Table<Administrator> Administrators;
public Table<Appointment> Appointments;
public Table<ExaminationType> ExaminationTypes;
public Table<LaboratoryExamination> LaboratoryExaminations;
public Table<Patient> Patients;
public Table<PhysicalExamination> PhysicalExaminations;
public BD_PROJ_GKiO3(IDbConnection connection) : base(connection)
{
}
}
ユーザーと管理者のマッピング:
[Table(Name = "Users")]
public class User
{
//kolumna PK w tabeli Users
[Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "Int NOT NULL IDENTITY")]
public int usrId { get; set; }
//Reszta kolumn
[Column] public string login { get; set; }
[Column] public string password { get; set; }
[Column] public string role { get; set; }
[Column] public string status { get; set; }
[Column] public int staffId { get; set; }
//Mapowanie relacji z tabelami aktorów
private EntitySet<Doctor> _Doctors;
[Association(Storage = "_Doctors", OtherKey = "docId", ThisKey = "staffId")]
public EntitySet<Doctor> Doctors
{
get { return this._Doctors; }
set { this._Doctors.Assign(value); }
}
private EntitySet<Registrator> _Registrators;
[Association(Storage = "_Registrators", OtherKey = "registratorId", ThisKey = "staffId")]
public EntitySet<Registrator> Registrators
{
get { return this._Registrators; }
set { this._Registrators.Assign(value); }
}
private EntitySet<Administrator> _Administrators;
[Association(Storage = "_Administrators", OtherKey = "adminId", ThisKey = "staffId", IsForeignKey = true)]
public EntitySet<Administrator> Administrators
{
get { return this._Administrators; }
set { this._Administrators.Assign(value); }
}
private EntitySet<LaboratoryManager> _LaboratoryManagers;
[Association(Storage = "_LaboratoryManagers", OtherKey = "laboratoryPrincipalId", ThisKey = "staffId")]
public EntitySet<LaboratoryManager> LaboratoryManagers
{
get { return this._LaboratoryManagers; }
set { this._LaboratoryManagers.Assign(value); }
}
private EntitySet<LaboratoryWorker> _LaboratoryWorkers;
[Association(Storage = "_LaboratoryWorkers", OtherKey = "laboratoryWorkerId", ThisKey = "staffId")]
public EntitySet<LaboratoryWorker> LaboratoryWorkers
{
get { return this._LaboratoryWorkers; }
set { this._LaboratoryWorkers.Assign(value); }
}}
[Table(Name = "Administrators")]
public class Administrator
{
//PK w tabeli Administrators
[Column(IsPrimaryKey = true, IsDbGenerated = true)]
public int adminId { get; set; }
//Reszta kolumn
[Column] public string name { get; set; }
[Column] public string surname { get; set; }
//Mapowanie relacji tabeli Administrators z tabelą Users
private EntitySet<User> _Users;
[Association(Storage = "_Users", OtherKey = "staffId", IsForeignKey = true, ThisKey = "adminId")]
public EntitySet<User> Users
{
get { return this._Users; }
set { this._Users.Assign(value); }
}}
もちろん、両方のクラスにコンストラクターがありますが、ここには貼り付けませんでした (必要な場合は貼り付けます)。
上記のように、テーブルとリレーションをデータベースからオブジェクトにマッピングした方法がわかります。
問題は、テーブル Users の既存の行をテーブル Administrators の関連する行で更新しようとしているときです。テーブル行を更新する必要があるデータを格納するユーザー インスタンス (toUpdate) を作成しました。次に、それに管理者インスタンス データ (admin) を追加します。最初に - DataContext オブジェクトを取得しています。次に - ユーザーが編集するデータベースを探しています。
最初に:
BD_PROJ_GKiO3 newDB = new BD_PROJ_GKiO3(Program.getConnection());
User u = newDB.Users.SingleOrDefault(us => us.usrId == currentlyEdited.usrId);
適切なユーザー (u) が見つかったので、以下のコードを実行しようとしています。
u.login = toUpdate.login;
u.role = toUpdate.role;
u.status = toUpdate.status;
u.staffId = toUpdate.staffId;
u.Administrators.ElementAt(0).name = admin.name;
u.Administrators.ElementAt(0).surname = admin.surname;
newDB.SubmitChanges();
そして、最後の行 (newDB.SubmitChanges()) の実行中に NullReferenceException がスローされます。
スタック トレース: ExceptionStackTrace
私を助けようとするすべての人に前もって感謝します、私はとても感謝しています!編集:この方法で作成およびマッピングされたデータベースはおそらくうまくいくと思います。アプリケーションの起動時に、プログラムのパブリックフィールド(アプリケーションルート)として新しいデータベースを作成し、それを使用してユーザーはログインする可能性があり、完全に機能します (ログイン手順では、ユーザーや管理者などからのデータを確認する必要があります)。