Это можно сделать с помощью filter_at
, указав интересующие столбцы
library(dplyr)
df1 %>%
filter_at(vars(col1, col2), all_vars(. != 0))
df1 <- data.frame(col1 = c(0, 1, 2, 3), col2 = c(1, 0, 2, 4), col3 = c(1, 1, 0, 0))
Вам нужно построить дерево выражений, которое может понять LINQ to SQL . Предполагая, что ваше свойство "id" всегда называется "id":
public virtual T GetById<T>(short id)
{
var itemParameter = Expression.Parameter(typeof(T), "item");
var whereExpression = Expression.Lambda<Func<T, bool>>
(
Expression.Equal(
Expression.Property(
itemParameter,
"id"
),
Expression.Constant(id)
),
new[] { itemParameter }
);
var table = DB.GetTable<T>();
return table.Where(whereExpression).Single();
}
Это должно сработать. Он был бесстыдно заимствован из этого блога . Это в основном то, что делает LINQ to SQL, когда вы пишете запрос, подобный
var Q = from t in Context.GetTable<T)()
where t.id == id
select t;
. Вы просто выполняете работу для LTS, потому что компилятор не может создать это для вас, поскольку ничто не может навязать то, что у T есть свойство "id", и вы не можете отобразить произвольное свойство "id" из интерфейса с базой данных.
==== UPDATE ====
Хорошо, вот простая реализация для поиска имени первичного ключа, при условии, что есть только один (не составной) первичный ключ) и при условии, что все хорошо по типу (т. е. ваш первичный ключ совместим с «коротким» типом, который вы используете в функции GetById):
public virtual T GetById<T>(short id)
{
var itemParameter = Expression.Parameter(typeof(T), "item");
var whereExpression = Expression.Lambda<Func<T, bool>>
(
Expression.Equal(
Expression.Property(
itemParameter,
GetPrimaryKeyName<T>()
),
Expression.Constant(id)
),
new[] { itemParameter }
);
var table = DB.GetTable<T>();
return table.Where(whereExpression).Single();
}
public string GetPrimaryKeyName<T>()
{
var type = Mapping.GetMetaType(typeof(T));
var PK = (from m in type.DataMembers
where m.IsPrimaryKey
select m).Single();
return PK.Name;
}
Что, если вы переделаете это для использования GetTable (). Where (...) и поместите туда свою фильтрацию?
Это было бы более эффективно, поскольку метод расширения Where должен принимать заботиться о вашей фильтрации лучше, чем извлекать всю таблицу из списка.
Some thoughts...
Just remove the ToList() call, SingleOrDefault works with an IEnumerably which I presume table is.
Cache the call to e.GetType().GetProperties().First() to get the PropertyInfo returned.
Cant you just add a constraint to T that would force them to implement an interface that exposes the Id property?
Относительно:
System.NotSupportedException: член 'MusicRepo_DataContext.IHasID.ID' не имеет поддерживаемого перевода в SQL
Простой обходной путь к вашей первоначальной проблеме - указать выражение. Смотрите ниже, это работает для меня как прелесть.
public interface IHasID
{
int ID { get; set; }
}
DataContext [View Code]:
namespace MusicRepo_DataContext
{
partial class Artist : IHasID
{
[Column(Name = "ArtistID", Expression = "ArtistID")]
public int ID
{
get { return ArtistID; }
set { throw new System.NotImplementedException(); }
}
}
}
Возможно, выполнение запроса может быть хорошей идеей.
public static T GetByID(int id)
{
Type type = typeof(T);
//get table name
var att = type.GetCustomAttributes(typeof(TableAttribute), false).FirstOrDefault();
string tablename = att == null ? "" : ((TableAttribute)att).Name;
//make a query
if (string.IsNullOrEmpty(tablename))
return null;
else
{
string query = string.Format("Select * from {0} where {1} = {2}", new object[] { tablename, "ID", id });
//and execute
return dbcontext.ExecuteQuery<T>(query).FirstOrDefault();
}
}