Linq to sql中方法未注册,数据类型转换等问题

这次要记录一个不是问题的问题的解决方法。

我之前有一张表(sqlserver数据库),其中有一个字段是nvarchar类型,但是由于某些特殊需求,我需要在linq查询中将这个字段转换为int类型并排序,一般我们是写int.parse或者convert.toint32,这时一般会报一个不支持对未注册方法的调用。平时我们一般在where条件里用的数据类型转换或者时间加减,这种在where外面提前转换好即可,但是我的场景是要用来排序,必须在linq中进行转换,这是前提。其实最简单的方法:在数据库里把这个字段的类型改了就完事。下面讲复杂的方法:

经过搜索之后呢,发现ef框架提供了这么两个静态类:dbfunctions、sqlfunctions,这里面封装了好多方法,尤其是对datetime类型的操作,非常友好,比如之前我们写一个where:

query=query.where(d=>d.addtime>datetime.now.adddays(-3)),这里肯定报错,我们一般会改为:

var targettime=datetime.now.adddays(-3);

query=query.where(d=>d.addtime>targettime);

其实我们还可以这样写:

query=query.where(d=>d.addtime>DbFunctions.AddDays(datetime.now,3));

但遗憾的是,dbfunctions与sqlfunctions里均没有提供nvarchar转int的方法,然后我通过.net reflector看到了dbfunctions、sqlfunctions下方法的实现,

 [DbFunction("Edm", "AddDays")]

 public static DateTimeOffset? AddDays(DateTimeOffset? dateValue, int? addValue);

原来它们是直接对应了sqlserver自带函数,比如上面的DbFunctions.AddDays,其实就是在linq翻译到sql语句时,转换为了DATEADD(day,getdate(),3),这时我就有了思路了,自己去数据定义一个标量值函数,然后在C#代码里想办法去调用到它即可。

然后我就仿照它的实现去写了一个,然后在linq里调用,发现还是报错误未注册的方法,后来经过一系列的查找,最终在github上找到了答案,就是这个东西我们们定义了之后,需要在protected override void OnModelCreating(DbModelBuilder modelBuilder)里注册一下即可:

方法定义如下,这个方法写在dbcontext里就行:

public class UserDbFunction { [DbFunction("CodeFirstDatabaseSchema", "IntParse")]//这个IntParse是我自己定义的函数 public static int IntParse(string arg1) { throw new NotSupportedException();//这里就为了能编译通过,真正调用时与它无关 } }

注册如下,在代码里搜索全局:override void OnModelCreating即可找到这个地方,一般就是我们的dbcontext里:

protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Conventions.Add(new FunctionsConvention("dbo", typeof(UserDbFunction))); base.OnModelCreating(modelBuilder); }

有的人那里会提示FunctionsConvention这个没有,我们去.nuget上安装一个EntityFramework.CodeFirstStoreFunctions即可

CodeFirstDatabaseSchema这个东西是EntityFramework.CodeFirstStoreFunctions要求的名称

然后在linq里去调用这个方法就齐活啦,我们调试跟踪下这个方法在sql中已经被翻译成dbo.IntParse(t1.Exten1)

到此,这个问题解决

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值