在 WinForms 应用程序内的 EF DataContext 中,我有多个具有相同布局的表:ID、描述。但是,每个表中的 ID 字段都有不同的名称(“ProductTypeID”、“SubTypeID”、“ProducerID”...)。
我想使用单一表单对此类表进行 CRUD 操作,所以这就是我所做的:
ProductType.cs、SubType.cs、Producer.cs等
[Table("ProductType")]
public class ProductType : IGenericTable
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ProductTypeID { get; set; } = -1; // the name of this property is different in every table
public string Description { get; set; }
[NotMapped]
public int ID { get => ProductTypeID; set => ProductTypeID = value; } // used in generic form
}
IGenericTable.cs
internal interface IGenericTable
{
public int ID { get; set; }
public string Description { get; set; }
}
GenericForm.cs
internal partial class GenericForm<T> : Form where T : class, IGenericTable, new()
{
// T.Description property is bound to a textbox.
private BindingSource bs = new();
private MODataContext dc;
public T Item { get => (T)bs.Current; }
public GenericForm(MODataContext dc, T item)
{
InitializeComponent();
if (item == null) item = new();
bs.DataSource = item;
this.dc = dc;
}
private void cmdOK_Click(object sender, System.EventArgs e)
{
var cur = (T)bs.Current;
if (cur.ID == -1) dc.Set<T>().Add(cur);
dc.SaveChanges();
this.Close();
}
}
这样我就可以重用相同的表单来创建和编辑所有不同表中的记录。我做了类似查询和删除记录的事情。
我想为具有相同描述的现有记录添加检查
cmdOK_Click
,所以我尝试了以下方法:
private void cmdOK_Click(object sender, System.EventArgs e)
{
var cur = (T)bs.Current;
var set = dc.Set<T>();
if (set.Any(x => x.ID != cur.ID && x.Description == txtDescription.Text.Trim())) // EXCEPTION HERE
{
MessageBox.Show("A record with the same description already exists!", "Warning!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
if (cur.ID == -1) dc.Set<T>().Add(cur);
dc.SaveChanges();
this.Close();
}
但是这段代码会抛出以下异常: System.NotSupportedException:“LINQ to Entities 不支持指定的类型成员“ID”。仅支持初始值设定项、实体成员和实体导航属性。'
我认为这是因为ID列没有映射到db中的列。 假设我无法更改数据库列名称,我尝试将特定 ID 列和通用 ID 列关联到数据库中的同一列,但这是不允许的:
// This does not work
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity), Column("ProductTypeID")]
public int ProductTypeID { get; set; } = -1; // the name of this property is different in every table
public string Description { get; set; }
[Column("ProductTypeID")]
public int ID { get => ProductTypeID; set => ProductTypeID = value; } // used in generic form
在这种情况下,EF 抱怨我不能将两个属性映射到同一列。
有什么线索吗?
if (set.Any(x => x.ID != cur.ID && x.Description == txtDescription.Text.Trim()))
您不能使用 NotMapped 进行查询。通过过滤之前获取数据记录
set.ToList()