一般的想法从创建一个控件开始,该控件适用于任何数据库对象。 通过LINQ to SQL访问数据库,并从现有数据库自动生成数据库对象。
为了使控件能够与这些对象中的任何一个一起使用,我使用了一个基本接口,所有自动生成的对象都从该接口继承。因此控件实际上适用于该界面。
此界面首先应提供:
所以这看起来像:
public interface IEntity<TEntity, TEntityId>
where TEntity : IEntity<TEntity, TEntityId>
where TEntityId : IEquatable<TEntityId>
{
Expression<Func<TEntity, TEntityId>> GetIdExpression();
TEntityId EntityId { get; }
}
然后数据库对象的类定义如下:
//let it be the auto-generated part:
public partial class Entity1
{
public Guid UId { get; set; }
}
//and the manual part:
public partial class Entity1 : IEntity<Entity1, Guid>
{
public Expression<Func<Entity1, Guid>> GetIdExpression()
{
return (Expression<Func<Entity1, Guid>>)(se => se.UId);
}
public Guid EntityId
{
get { return this.UId; }
}
}
我们可以测试一下:
var e1 = new Entity1();
e1.UId = Guid.NewGuid();
Console.WriteLine(e1.UId);
Console.WriteLine(e1.GetIdExpression().Compile()(e1));
这两条线的输出相等。没关系。
下一个想法是,所有数据库对象的狮子份额都有int
标识符,名称为Id
。最好避免编辑每一个,即不要编写实现IEntity<TEntity, TEntityId>
的同一个代码。
至于我需要指定这个接口的实现,我需要一个类。 现在我最终得到了
public class IntEntity<TEntity> : IEntity<TEntity, int>
where TEntity : IntEntity<TEntity>
{
public int Id { get; set; }
public Expression<Func<TEntity, int>> GetIdExpression()
{
return (Expression<Func<TEntity, int>>)(e => e.Id);
}
public int EntityId
{
get { return this.Id; }
}
}
然后数据库对象类将从中派生出来:
//let it be the auto-generated part:
public partial class Entity2
{
public int Id { get; set; }
}
//and the manual part:
public partial class Entity2 : IntEntity<Entity2>
{
}
现在很明显,Id
中的Entity2
确实隐藏了Id
中的IntEntity<TEntity>
。同样的测试也证明了这一点:
var re = new Entity2();
re.Id = 5;
Console.WriteLine(re.Id); //5
Console.WriteLine(re.GetIdExpression().Compile()(re)); //0
所以这个解决方案错了......
我还尝试将IntEntity<TEntity>
抽象化,但显然失败了,因为Entity2
Id
在自动生成的部分中已定义,而我无法使override
成为{基类的{1}} abstract
。
我能做些什么来使Id
的所有数据库对象都使用基础int Id
类中的Id
。或者,可能反过来......
这里的要点是IntEntity<TEntity>
返回的表达式应该具有GetIdExpression
形式,因为此表达式稍后将用于LINQ to SQL查询,因此LINQ应该能够将其转换为一个正确的SQL查询。
答案 0 :(得分:0)
我不确定这正是你想要的,但你可以尝试这样做
public abstract class IntEntity<TEntity> : IEntity<TEntity, int>
where TEntity : IntEntity<TEntity>
{
public abstract Expression<Func<TEntity, int>> GetIdExpression();
public abstract int EntityId
{
get;
}
}
public partial class Entity2
{
public int Id { get; set; }
}
//and the manual part:
public partial class Entity2 : IntEntity<Entity2>
{
public override int EntityId
{
get { return this.Id; }
}
public override Expression<Func<Entity2, int>> GetIdExpression()
{
return (Expression<Func<TEntity, int>>)(e => e.Id);
}
}
实际上没有override
virtual
您无法从基类中的方法访问derive类中的字段
事实上,上面的样本等于你的第一个样本
<强>更新强>
作为解决方法,您可以添加方法SetId,它在derive和base类中设置id,就像这样
public class IntEntity<TEntity> : IEntity<TEntity, int>
where TEntity : IntEntity<TEntity>
{
public int Id { get; set; }
public Expression<Func<TEntity, int>> GetIdExpression()
{
return (Expression<Func<TEntity, int>>)(e => e.Id);
}
public int EntityId
{
get { return this.Id; }
}
}
//let it be the auto-generated part:
public partial class Entity2
{
public int Id { get; set; }
}
//and the manual part:
public partial class Entity2 : IntEntity<Entity2>
{
public void SetId(int id)
{
Id = id;
base.Id = id;
}
}
var re = new Entity2();
re.SetId(5);
Console.WriteLine(re.Id); //5
Console.WriteLine(re.GetIdExpression().Compile()(re)); //5