喜欢这个主题。我需要遍历实体的每个属性和复杂类型的属性,并检查它的值是否与给定值相似。我做了类似这样的事情,但效率非常低,在三个记录表中找到值需要1-2秒。如何制作更快?我尝试将其重写为linq,但每次尝试都失败了。
private List<AddressBook> SearchContact(string searchText)
{
var ToReturn = new List<AddressBook>();
using (var cntx = Model.DBService.Instance.CreateContext())
{
foreach (var s in cntx.AddressBooks.ToList())
{
Type AddressBookProperties = s.GetType();
Type PersonInfoProperties = s.PersonInfo.GetType();
Type AddressProperties = s.Address.GetType();
foreach (PropertyInfo prop in AddressBookProperties.GetProperties())
{
try
{
if (prop.GetValue(s).ToString().Contains(searchText))
{
ToReturn.Add(s);
break;
}
}
catch { }
}
foreach (PropertyInfo prop in PersonInfoProperties.GetProperties())
{
try
{
if (prop.GetValue(s).ToString().Contains(searchText))
{
ToReturn.Add(s);
break;
}
}
catch { }
}
foreach (PropertyInfo prop in AddressProperties.GetProperties())
{
try
{
if (prop.GetValue(s).ToString().Contains(searchText))
{
ToReturn.Add(s);
break;
}
}
catch { }
}
}
}
return ToReturn;
}
型号:
public class AddressBook
{
public AddressBook()
{
this.Address = new Address();
this.PersonInfo = new PersonInfo();
}
[Key]
public int AddressBookID { get; set; }
public Address Address { get; set; }
public PersonInfo PersonInfo { get; set; }
public String RecordName { get; set; }
public Boolean isPerson { get; set; }
public Boolean isFirm { get; set; }
public virtual Template Template { get; set; }
}
public class PersonInfo
{
private string fullName { get; set; }
public string Fullname
{
get
{
if (fullName == null)
{
fullName = Firstname + " " + Surname;
return Firstname + " " + Surname;
}
return fullName;
}
set
{
fullName = value;
}
}
public string Firstname { get; set; }
public string Surname { get; set; }
public string Email { get; set; }
public string ExtField { get; set; }
public string Phone { get; set; }
public string NIP { get; set; }
public string MobilePhone { get; set; }
public string Fax { get; set; }
}
public class Address
{
public string CompanyName { get; set; }
public string Street { get; set; }
public string HouseNumber { get; set; }
public string FlatNumber { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
public string PostOffice { get; set; }
public string Commune { get; set; }
public string City { get; set; }}
答案 0 :(得分:1)
您可以通过构建动态表达式树来完成此操作,以便在数据库上完成所有处理。这里有一些代码可以帮助您入门:
private static IEnumerable<Expression> GetConditions(Expression instance, Expression searchTerm)
{
// note: if you have properties like FullName that don't map directly
// to database columns, you'll need to filter those out here
var stringProperties = @object.Type.GetProperties()
.Where(p => p.PropertyType == typeof(string));
// GetMethod from
// http://www.codeducky.org/10-utilities-c-developers-should-know-part-two/
var containsMethod = Helpers.GetMethod((string s) => s.Contains(default(string)));
// for each property, generate an expression
// instance.Prop.Contains(searchTerm)
return stringProperties.Select(p =>
Expression.Call(
Expression.MakeMemberAccess(instance, p),
containsMethod,
searchTerm
)
);
}
// use the above method like so:
var bookParameter = Expression.Parameter(typeof(AddressBook));
var personInfo = Expression.MakeMemberAccess(
bookParameter,
typeof(AddressBook).GetProperty("PersonInfo")
);
// ... create more for other complex types
var searchTermExpression = Expression.Constant(searchTerm);
var allConditions = GetConditions(bookParameter, searchTermExpression)
.Concat(GetConditions(personInfo, searchTermExpression))
// ... add conditions for other complex types
// combine the conditions into a single expression with OR:
// ab.RecordName.Contains(...) || ab.PersonInfo.Name.Contains(...)...
var combinedCondition = allConditions.Aggregate(Expression.OrElse);
// create a lambda which you can pass to Where()
// ab => ab.RecordName.Contains(...) || ab.PersonInfo.Name.Contains(...)...
var lambda = Expression.Lambda<Func<AddressBook, bool>>(
combinedCondition,
bookParameter
);
// filter the query
var filtered = ctxt.AddressBooks.Where(lambda);