简体   繁体   English

LINQ查询实体框架中的if控件

[英]If control in linq query entity framework

,Hi ,喜

List<Claimant> list = (from c in CacheManager.ClaimantList.List
where 

     c.Fullname.Replace("i", "İ").Replace("ı","I").ToUpper().Contains(searchKey.Replace("i", "İ").Replace("ı", "I").ToUpper())
  || c.IdentityNumber.Replace("i", "İ").Replace("ı", "I").ToUpper().Contains(searchKey.Replace("i", "İ").Replace("ı", "I").ToUpper())
  || c.TaxNumber.Replace("i", "İ").Replace("ı", "I").ToUpper().Contains(searchKey.Replace("i", "İ").Replace("ı", "I").ToUpper())

 select c).Take(20).ToList<Claimant>();

If Taxnumber is null or "" i get exception because of null data. 如果Taxnumber为null或“”,则由于数据为空,我将获得异常。

My question: 我的问题:

How can i set Taxnumber == 0 , if Taxnumber is null or "" ? 如果Taxnumber为null或“” ,如何设置Taxnumber == 0?

Any help will be appreciated. 任何帮助将不胜感激。

Thanks. 谢谢。

You can do: 你可以做:

from c in CacheManager.ClaimantList.List
let taxNumber = c.TaxNumber == null || c.TaxNumber == "" ? "0" : c.TaxNumber
where ...

and then use the taxNumber variable rather than the column. 然后使用taxNumber变量而不是列。

If you just want certain columns and you don't need the whole Claimant object, you can put something into a select 如果只需要某些列,而又不需要整个Claimant对象,则可以将一些内容放入select

from c in ClaimantList
where (...)
select new {c.FullName, c.IdentityNumber, TaxNumber = String.IsNullOrEmpty(c.TaxNumber) ? "0" : c.TaxNumber}

You now have an anonymous type with three fields: original FullName , original IdentityNumber and modified TaxNumber . 现在,您将具有一个带有三个字段的匿名类型:原始FullName ,原始IdentityNumber和已修改的TaxNumber


You could also create a new Claimant for each value by calling its constructor each time: 您还可以通过每次调用其构造函数来为每个值创建一个新的Claimant

from c in ClaimantList
where (...)
select new Claimant() {FullName = c.FullName, IdentityNumber = c.IdentityNumber, TaxNumber = String.IsNullOrEmpty(c.TaxNumber) ? "0" : c.TaxNumber}

(I don't know what the constructor of Claimant is like, you might do this slightly differently and set those values in the constructor rather than in the initializer. Or you could write a new constructor.) If the constructor does something non-trivial, it might be wasteful of resources to call it this many times. (我不知道Claimant的构造函数是什么样的,您可能会做些不同的操作,并在构造函数中而不是在初始化程序中设置这些值。或者您可以编写一个新的构造函数。)如果构造函数执行了一些琐碎的事情,多次调用它可能会浪费资源。

In either case, it is stylistically nice to put the conversion ( String.IsNullOrEmpty(TaxNumber) ? "0" : TaxNumber or whatever) into its own function somewhere, so that you can change what conversion you do later (see below), and don't have to repeat the code in multiple places. 无论哪种情况,从风格上来说,都可以将转换( String.IsNullOrEmpty(TaxNumber) ? "0" : TaxNumber或其他内容)放在自己的函数中,这样您就可以更改以后执行的转换(请参见下文),以及不必在多个地方重复代码。


Another option is that you could use the objects you have, but change the TaxNumber as required. 另一个选择是您可以使用已有的对象,但TaxNumber根据需要更改TaxNumber LINQ isn't really the best way of doing this, as you are basically applying side-effects. LINQ并不是真正做到这一点的最佳方法,因为您基本上是在应用副作用。 (LINQ likes to supply a new container with the right data in it, rather than change the data in the original container.) You should really run foreach outside of the Linq code, like this: (LINQ喜欢在其中提供正确数据的新容器,而不是更改原始容器中的数据。)您确实应该在Linq代码之外运行foreach ,如下所示:

List<Claimant> list = from ...
                      where ...
                      select ...

foreach (Claimant claimant in list)
{
    if (String.IsNullOrEmpty(claimant.TaxNumber))
    { claimant.TaxNumber = "0"; }
}

Ideally you do this after the Take(20) so that you only do it the number of times you need. 理想情况下,您可以在Take(20)之后执行此操作,以便仅执行所需次数。


Again, putting the conversion in a function will be neater and nicer: 同样,将转换放入函数中将变得更加简洁:

List<Claimant> list = from ...
                      where ...
                      select ...

foreach (Claimant claimant in list)
{
    claimant.TaxNumber = NormalizeTaxNumber(claimant.TaxNumber); }
}

// ...

public static string NormalizeTaxNumber(string n)
{
    return String.IsNullOrEmpty(n) ? "0" : n;
}

However, if you have gone down this route, the next option is to add a method to Claimant which does this change: 但是,如果您走了这条路线,那么下一个选择是向Claimant添加一个方法来进行此更改:

List<Claimant> list = from ...
                      where ...
                      select ...

foreach (Claimant claimant in list)
{
    claimant.NormalizeTaxNumber();
}

public class Claimant
{
    // ...

    public void NormalizeTaxNumber()
    {
        if (String.IsNullOrEmpty(TaxNumber))
        { TaxNumber = "0"; }
    }
}

and to call this from the foreach loop. 并从foreach循环中调用它。


Or, use a different property than TaxNumber : 或者,使用与TaxNumber不同的属性:

public class Claimant
{
    // ...

    public string NormalTaxNumber
    {
        get { return String.IsNullOrEmpty(TaxNumber) ? "0" : TaxNumber; }
    }
}

The advantage of the first strategy is that you only have to call it once - the advantages of the second are that it keeps the original value still available (in the TaxNumber property), and that if you have a bunch of Claimant objects, you don't have to remember whether you have normalized them or not. 第一种策略的优点是您只需要调用一次即可-第二种策略的优点是它使原始值仍然可用(在TaxNumber属性中),并且如果您有一堆Claimant对象,则不必不必记住您是否已将它们标准化。


You could also use a combination of the two methods: add a new property NormalTaxNumber which converts TaxNumber when needed, and which caches the result so that conversion doesn't have to be done again. 您也可以使用两种方法的组合:添加一个新属性NormalTaxNumber ,该属性在需要时转换TaxNumber ,并缓存结果,从而不必再次进行转换。

public class Claimant
{
    // ...

    private string m_normalTaxNumber;

    private string ConvertedTaxNumber
    {
        get { return String.IsNullOrEmpty(TaxNumber) ? "0" : TaxNumber; }
    }

    public string NormalTaxNumber
    {
        get
        {
            if (m_normalTaxNumber == null)
            { m_normalTaxNumber = ConvertedTaxNumber; }
            return m_normalTaxNumber;
        }
    }
}

This only does the calculation once, keeps the original still available, and doesn't require to remember if you've called it before or not. 这仅进行一次计算,使原始数据仍然可用,并且不需要记住您之前是否调用过它。 If TaxNumber (the original value) isn't readonly, this is probably more trouble than it's worth as you will have to invalidate the cached value. 如果TaxNumber (原始值)不是只读的,则可能要麻烦得多,因为您必须使缓存的值无效。


If you are never, never going to need to know whether the TaxNumber was originally null, empty or "0", the best advice (and the last strategy) is to convert to the form you want as soon as possible, preferably in the Claimant constructor, if the value of TaxNumber is known there. 如果您从未使用过,也永远不需要知道TaxNumber最初是空,为空还是为“ 0”,那么最好的建议(也是最后一种策略)是尽快转换为您想要的格式,最好在Claimant构造函数,如果在那里知道TaxNumber的值。

If you are getting Claimant objects from a database, you could take this to its logical limit by doing the conversion on the database, either in a stored proc or in a view. 如果要从数据库中获取Claimant对象,则可以通过在存储proc或视图中对数据库进行转换来将其达到逻辑极限。 If you are using LinqToSql to get the list of Claimant objects, a view could work for you but a stored proc might not. 如果使用LinqToSql来获取Claimant对象的列表,则视图可能对您有用,但存储的proc可能无效。


I have assumed throughout that you want TaxNumber to be available as a string, and that by 0 you mean the string "0". 我一直假设您希望TaxNumber作为字符串提供,并且0表示字符串“ 0”。 If this isn't the case, and you actually want convert to an int (or similar), some of the strategies above will still work. 如果不是这种情况,并且您实际上想转换为int (或类似值),则上面的某些策略仍然有效。 You can select the converted value as an int in an anonymous type, you can make a new property NormalTaxNumber (with int type), whether cached or not cached, or you can do the conversion upon creation of a Claimant object. 您可以将转换后的值select为匿名类型的int类型,可以创建新属性NormalTaxNumber (具有int类型)(无论是否缓存),也可以在创建Claimant对象时进行转换。 Obviously you can't overwrite the string TaxNumber with an int . 显然,您不能使用int覆盖string TaxNumber

If you are parsing the string to an int , things like NormalTaxNumber with caching become more worthwhile, because the conversion from string to int is more costly. 如果将string解析为int ,则诸如带有缓存的NormalTaxNumber东西变得更有价值,因为从stringint的转换成本更高。 (Checking for null or "" is actually very fast, however I thought it valuable to go through some different options anyway.) (检查null""实际上非常快,但是我认为无论如何都要经过一些不同的选择很有价值。)

Note that almost all of these should still be available to you if you can't modify the Claimant class. 请注意,如果您无法修改Claimant类,那么几乎所有这些内容仍然对您可用。 You can't write a new constructor, but you can write a factory method which encapsulates exactly the same behavior as a constructor. 您不能编写新的构造函数,但是可以编写一个工厂方法,该方法封装与构造函数完全相同的行为。 You can add NormalizeTaxNumber as an extension method, and while you can't add properties, you can add extension methods with no arguments which work almost exactly like properties. 您可以将NormalizeTaxNumber添加为扩展方法,虽然不能添加属性,但是可以添加不带参数的扩展方法,这些参数的工作原理几乎与属性相同。

My last observation is that "0" might not necessarily be a better value for missing data than null or "" . 我的最后观察结果是,对于丢失数据, "0"不一定比null""更好。 Either of the latter is more commonly used to indicate missing values, especially null . 后者更常用来表示缺失值,尤其是null Perhaps you should choose one of those as the default (and maybe apply one of the above strategies in reverse to enforce it as the only 'N/A' value?) If it's just a question of it looking nice when you print the object out, you could override ToString() to swap in the "0" only when needed. 也许您应该选择其中之一作为默认值(也许可以反过来应用上述策略之一,以将其强制为唯一的“ N / A”值?)如果只是一个问题,那么在打印出对象时它看起来就不错了,您可以覆盖ToString()以仅在需要时将其交换为"0"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM