Как насчет использования метода расширения следующим образом:
public static T FirstOrCreate<T>(this IEnumerable<T> source) where T : class, new()
{
var result = source.FirstOrDefault();
return result != null ? result : new T();
}
Если вы хотите, чтобы он мог принимать предикат, вы можете использовать это определение:
public static T FirstOrCreate<T>(this IQueryable<T> source, Expression<Func<T, bool>> predicate) where T : class, new()
{
var result = source.FirstOrDefault(predicate);
return result != null ? result : new T();
}
Таким образом, вы можете использовать его вместо FirstOrDefault () следующим образом:
Invoice selectedInvoice = (from i in Invoices
where i.ID == invoiceID
select i).FirstOrCreate();
.. или с использованием предиката:
Invoice selectedInvoice = db.Invoices.FirstOrCreate(i => i.ID == invoiceID);
Вместо этого будет возвращать соответствующий объект или новый (не нулевой) объект.
Редактировать: я думал об этом сегодня, и мне пришло в голову, что вышеизложенное потребует от вас обнаружить, что объект является новым (не существует), и присоединить его к DataContext, поэтому я пришел к этому компромиссу , используя тот же подход:
public static T FirstOrCreate<T>(this IEnumerable<T> source, DataClassesDataContext db) where T : class, new()
{
var result = source.FirstOrDefault();
if (result == null)
{
result = new T();
db.GetTable<T>().InsertOnSubmit(result);
}
return result;
}
Недостатком является то, что вы должны передавать DataContext в качестве параметра, но он должен работать достаточно хорошо:
Customer selectedCustomer = (from c in db.Customers
where c.CustomerId == selectedCustomerId
select c).FirstOrCreate(db);
Конечно, есть одно возражение? :)