5

LINQ または DbContext 拡張メソッドを追加して要素 (FirstOrDefault) を取得しようとしていますが、まだ存在しない場合は、null を返す代わりに、データ (FirstOrCreate) を使用して新しいインスタンスを作成します。

これは可能ですか?

すなわち:

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 // ??? 
        }
    }
}

使用法は次のとおりです。

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
    });
}

私のアプローチを理解していただければ幸いです。

4

4 に答える 4

2
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();
    }
}

利用方法

var status = db.EntitiesStatus.FirstOrCreate(s => s.Name == "Enabled", 
                 () => new EntityStatus {Name = "Enabled"});

ただし、これは のようには機能しないことに注意してくださいFirstOrDefault()

次のことをした場合

var listOfStuff = new List<string>() { "Enabled" };
var statuses = from s in listOfStuff
               select db.EntitiesStatus.FirstOrCreate(s => s.Name == "Enabled", 
                        () => new EntityStatus {Name = "Enabled"});

データベースへの O(n) ヒットを取得します。

しかし、あなたがしたかどうかは疑わしい...

var listOfStuff = new List<string>() { "Enabled" };
var statuses = from s in listOfStuff
               select db.EntitiesStatus.FirstOrDefault(s => s.Name == "Enabled") 
                             ?? new EntityStatus {Name = "Enabled"};

それが機能する可能性はもっともらしいです...

于 2013-05-31T02:09:09.860 に答える