我正在寻找一种更有效的方法来构建多个数据库列的分号分隔列表。我现在使用的代码看起来像这样(并且它可以工作):
//Process List of things
var things = DB.DbColumn_1.HasValue ? DB.DbColumn_1.Value.Equals(true) ? "thing 1;" : "" : "");
things += DB.DbColumn_2.HasValue ? DB.DbColumn_2.Value.Equals(true) ? "thing 2;" : "" : "");
things += DB.DbColumn_3.HasValue ? DB.DbColumn_3.Value.Equals(true) ? "thing 3;" : "" : "");
things += DB.DbColumn_4.HasValue ? DB.DbColumn_4.Value.Equals(true) ? "thing 4;" : "" : "");
// Remove final ';' from thing list if non-empty
things = things.Length > 0 ? things.Substring(0, things.Length-1) : things;
我实际上有大约8个要处理的列 - 这个例子让你有一些不足。所以我有一个很难看的代码块来构建一个简单的字符串。虽然这似乎工作得很好,但对于我正在尝试做的事情来说似乎有太多代码。另外,在这种情况下,我应该警惕使用“.Equals()”吗?
在一些头脑风暴之后,我想出了一些似乎没有比这更有效的东西,比如构建一个单独的函数来创建字符串本身。所有列都是唯一可空的bool,并且所有列都具有唯一的字符串输出。
或者我是否有效地访问这些元素而不用担心它?
谢谢!
答案 0 :(得分:2)
DB.DbColumn_1.HasValue && DB.DbColumn_1.Value.Equals(true)
是编写DB.DbColumn_1.GetValueOrDefault()
的一种非常困难的方式,但它们在功能上是等价的。在http://msdn.microsoft.com/en-us/library/1t3y8s4s(v=vs.80).aspx和http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx
bool?
相当于Nullable<bool>
,这是您的数据库列的类型) >
您可以使用以下方法之一:
var sections = new List<string>();
if (DB.DbColumn_1.GetValueOrDefault()) sections.Add("thing 1");
if (DB.DbColumn_2.GetValueOrDefault()) sections.Add("thing 2");
//...other columns
var things = string.Join(";", sections);
或者:
var pairs = new List<Tuple<bool?, string>>
{
Tuple.Create(DB.DbColumn_1, "thing 1"),
Tuple.Create(DB.DbColumn_2, "thing 2")
//...other columns
};
var things = string.Join(";", pairs.Where(x => x.Item1.GetValueOrDefault()).Select(x => x.Item2));
或只设置一次pairs
:
static readonly List<Tuple<Func<DBType, bool?>, string>> pairs = new List<Tuple<Func<DBType, bool?>, string>>
{
new Tuple<Func<DBType, bool?>, string>(d => d.DbColumn_1, "thing 1"),
new Tuple<Func<DBType, bool?>, string>(d => d.DbColumn_2, "thing 2")
//...other columns
};
void inSomeMethod()
{
var things = string.Join(";", pairs.Where(x => x.Item1(DB).GetValueOrDefault()).Select(x => x.Item2));
}
当然,这取决于具体情况,但我最喜欢最后一个。如果pairs
声明的详细程度困扰您(即重复Tuple<Func<DBType, bool?>, string>
),您可以这样做:
class ReadDbBools : Tuple<Func<DBType, bool?>, string>
{
public ReadDbBools(Func<DBType, bool?> retrieveFunc, string ifTrue) : base(retrieveFunc, ifTrue) { }
}
static readonly List<ReadDbBools> pairs = new List<ReadDbBools>
{
new ReadDbBools(d => d.DbColumn_1, "thing 1"),
new ReadDbBools(d => d.DbColumn_2, "thing 2")
//...other columns
};
答案 1 :(得分:0)
你可以稍微扩展你的linq-to-sql模型以返回你期望的值,所以你得到了那个部分:
public partial class Entity {
public string DbColumn_1_Display {
return (DbColumn_1 ?? false) ? "thing_1" : "";
}
/*for each property*/
}
然后选择它你可以这样做:
var result = from db in DB
select new {
c1 = DbColumn_1_Display,
c2 = DbColumn_2_Display /*etc*/};
var string = string.Format("{0};{1};{2}/*...*/", result.c1, result.c2 /*...*/);
不知道这是否会让事情变得更容易。
答案 2 :(得分:0)
从可以为空的类型开始,覆盖Equals
方法,而不是这个
DB.DbColumn_1.HasValue ? DB.DbColumn_1.Value.Equals(true) ? "thing 1;" : "" : ""
你可以写这个
DB.DbColumn_1.Equals(true) ? "thing1;" : ""
同样使用string.Join
是一种更简洁的方式来处理末尾的额外分号,这样就可以了:
var things = string.Join(";", new []
{
DB.DbColumn_1.Equals(true) ? "thing1" : null,
DB.DbColumn_2.Equals(true) ? "thing2" : null,
// etc...
}.Where(i => i != null));
这使得代码更具可读性,但是对于提高性能并不会有太大帮助,因为无论如何这个处理应该已经非常快了。