将接口置于具有相同名称但不同类型的属性后面 [英] Putting interface behind properties with same name but different types
问题描述
我有大约50个数据库,每个数据库有150个表,并且正在使用搜索机制来查询具有特定列的表。大多数数据库结构都是类似的,因此想法是生成EF实体并将接口放在生成的实体后面,如果生成它们的表具有特定的列,那么我以后可以查询该列。
I have a around 50 databases that have 150 tables each and working on a search mechanism that would allow to query the tables that have specific columns. Most database structures are similar so idea was to generate EF entities and put interfaces behind the entities generated if tables that they are being generated from have specific columns, so that I could later query then on that column.
长而在其他表上它是十进制
(oracle),有时它是 Nullable
,有时它不是。
After doing this I ran into unexpected problem on some tables column I am trying to map is Long
while on others it's Decimal
(oracle) and sometimes it's Nullable
and sometimes it's not.
我可以看到的一个解决方案是在运行查询之前添加没有任何属性的接口,并在运行时确定该列的特定类型。
One solution I can see to this is to add interface without any properties and when at runtime determine specific type of that column, before running the query.
有没有办法在接口上为可能有多种类型的属性添加一些类型,因此编译器不会抱怨没有实现?对象不起作用,请告诉我你是否需要代码示例作为问题有点复杂。
Is there a way to add some type on interface for property that might be more than one type so compiler wouldn't complain about not being implemented? object does not work, let me know if you need code examples as question is somewhat complicated.
我打算在实体上使用的机制:
Mechanism I intend to use on entities:
public static class ExpressionExtensions
{
public static IQueryable<T> ApplySearch<T>(this IQueryable<T> queryable, SearchModel search) where T : class
{
if (search != null && search.PolicyNumber.HasValue && typeof(IPolicyNumber).IsAssignableFrom(queryable.ElementType))
{
queryable = queryable.SearchByPolicyNumber(search);
}
return queryable;
}
public static IQueryable<IPolicyNumber> SearchByPolicyNumber<IPolicyNumber>(this IQueryable<IPolicyNumber> queryable, SearchModel search)
{
var policyNumberParameterLambda = Expression.Parameter((typeof(IPolicyNumber)));
var policyNumberColumnLambda = Expression.Property(policyNumberParameterLambda, "POLICY_NO");
var lambda = Expression.Lambda<Func<IPolicyNumber, bool>>(
Expression.Equal(policyNumberColumnLambda,
Expression.Convert(Expression.Constant(search.PolicyNumber), policyNumberColumnLambda.Type)
), policyNumberParameterLambda);
return queryable.Where(lambda);
}
}
推荐答案
想通过我自己
接口获取实体必须从此更改
Interface that gets put on entities has to change from this
public interface IUniqueId
{
long UNIQUE_ID { get; set; }
}
到此
public interface IUniqueId<T> : IUniqueId
{
T UNIQUE_ID { get; set; }
}
public interface IUniqueId
{
}
然后将界面置于实体
来自
public partial class QUOTE_HOUSE : IUniqueId
{
public long UNIQUE_ID { get; set; }
...
}
到
public partial class QUOTE_HOUSE : IUniqueId<long>
{
public long UNIQUE_ID { get; set; }
....
}
和 T4代码 生成接口改变自
public string EntityClassOpening(EntityType entity)
{
var stringsToMatch = new Dictionary<string,string> { { "POLICY_NO", "IPolicyNumber" }, { "UNIQUE_ID", "IUniqueId" } };
return string.Format(
CultureInfo.InvariantCulture,
"{0} {1}partial class {2}{3}{4}",
Accessibility.ForType(entity),
_code.SpaceAfter(_code.AbstractOption(entity)),
_code.Escape(entity),
_code.StringBefore(" : ", _typeMapper.GetTypeName(entity.BaseType)),
stringsToMatch.Any(o => entity.Properties.Any(n => n.Name == o.Key)) ? " : " + string.Join(", ", stringsToMatch.Join(entity.Properties, l => l.Key, r => r.Name, (l,r) => l.Value)) : string.Empty);
}
到
public string EntityClassOpening(EntityType entity)
{
var stringsToMatch = new Dictionary<string,string> { { "POLICY_NO", "IPolicyNumber" }, { "UNIQUE_ID", "IUniqueId" } };
return string.Format(
CultureInfo.InvariantCulture,
"{0} {1}partial class {2}{3}{4}",
Accessibility.ForType(entity),
_code.SpaceAfter(_code.AbstractOption(entity)),
_code.Escape(entity),
_code.StringBefore(" : ", _typeMapper.GetTypeName(entity.BaseType)),
stringsToMatch.Any(o => entity.Properties.Any(n => n.Name == o.Key)) ? " : " + string.Join(", ", stringsToMatch.Join(entity.Properties, l => l.Key, r => r.Name, (l,r) => string.Format("{0}<{1}{2}>", l.Value, r.TypeUsage.EdmType.Name, r.Nullable && r.TypeUsage.EdmType.Name!="String" ? "?" : ""))) : string.Empty);
}
Generics FTW确实......
Generics FTW indeed...
希望这能节省你一些时间。
Hope this saves you some time.
这篇关于将接口置于具有相同名称但不同类型的属性后面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!