I'd like a C# SingleOrNewIdentified(o => o.prop, value) function, responsible for returning a new o with o.prop = value preset when Any(o.prop == value) is not found. Unfortunately my understanding of expressions and lambdas is poor.

I frequently find myself needing to uniquely set just the one identifier (e.g. emailAddress, oauthId, GUID, natural key) before using a new EF object in a write-many manner. This write-once assignment often makes me shuffle some blocks around in a less-than-clear way.

It seems likely that it can be done since I'd be fine with reflection. I wouldn't want to defeat type checking in consumers of this function in any way, though.

Warnings about this idea are also welcome.

有帮助吗?

解决方案

public static T SingleOrNewIdentified<T, TProp>(this IQueryable<T> queryable, Expression<Func<T, TProp>> propExpr, TProp value) where T : class, new()
{
    var property = (PropertyInfo)((MemberExpression)propExpr.Body).Member;
    var paramExpr = Expression.Parameter(typeof(T));
    var eqExpr = Expression.Equal(Expression.Property(paramExpr, property), Expression.Constant(value));
    var predicate = Expression.Lambda<Func<T, bool>>(eqExpr, paramExpr);

    T maybe = queryable.SingleOrDefault(predicate);
    if (maybe != null) return maybe;

    T @default = new T();
    property.SetValue(@default, value);

    return @default;
}

其他提示

Not sure if this is what you want but it seems you can do it this way: if your collection is null, assign a default:

var foo = /*db.FooTable.*/SingleOrDefault(x => /*your where clause*/) ?? new Foo
                                              {
                                                  EmailMember = "me@foo.now"   
                                              }; 

It's not what I was looking for, but I thought I should note a related functionality for EF (update-or-create-by-indentity) for simplifying attaching at the end rather than beginning of your process, for entity keys only:

db.Attach(model);
db.SaveChanges();

It's been easy for me to forget that EF will do this work for you, but it maps especially well to UIs where create and update are very similar. You have to wait for SaveChanges() for a generated entity key of course.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top