将接口置于具有相同名称但不同类型的属性后面 [英] Putting interface behind properties with same name but different types

查看:149
本文介绍了将接口置于具有相同名称但不同类型的属性后面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有大约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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆