I'm trying to add a LINQ or DbContext extension method to get an element (FirstOrDefault) but if one does not already exist then create a new instance with data (FirstOrCreate) instead of returning null.
is this possible?
i.e.:
public static class LINQExtension
{
public static TSource FirstOrCreate<TSource>(
this IEnumerable<TSource> source,
Func<TSource, bool> predicate)
{
if (source.First(predicate) != null)
{
return source.First(predicate);
}
else
{
return // ???
}
}
}
and a usage could be:
using (var db = new MsBoxContext())
{
var status = db.EntitiesStatus.FirstOrCreate(s => s.Name == "Enabled");
//Here we should get the object if we find one
//and if it doesn't exist create and return a new instance
db.Entities.Add(new Entity()
{
Name = "New Entity",
Status = status
});
}
I hope that you understand my approach.
public static class LINQExtension
{
public static TSource FirstOrCreate<TSource>(
this IQueryable<TSource> source,
Expression<Func<TSource, bool>> predicate,
Func<T> defaultValue)
{
return source.FirstOrDefault(predicate) ?? defaultValue();
}
}
usage
var status = db.EntitiesStatus.FirstOrCreate(s => s.Name == "Enabled",
() => new EntityStatus {Name = "Enabled"});
However you must note that this will not work quite like FirstOrDefault()
.
If you did the following
var listOfStuff = new List<string>() { "Enabled" };
var statuses = from s in listOfStuff
select db.EntitiesStatus.FirstOrCreate(s => s.Name == "Enabled",
() => new EntityStatus {Name = "Enabled"});
You would get O(n) hits to the database.
However I suspect if you did...
var listOfStuff = new List<string>() { "Enabled" };
var statuses = from s in listOfStuff
select db.EntitiesStatus.FirstOrDefault(s => s.Name == "Enabled")
?? new EntityStatus {Name = "Enabled"};
It is plausible it could work...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With