csharp 实现.AddOrUpdate也支持nullables
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了csharp 实现.AddOrUpdate也支持nullables相关的知识,希望对你有一定的参考价值。
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace System.Data.Entity
{
internal static class DbSeeder
{
public static TEntity[] AddOrUpdate<TEntity>(this DbContext context, Expression<Func<TEntity, object>> identifiers, params TEntity[] entities)
where TEntity : class
{
// EF .AddOrUpdate is a bit buggy...
var primaryKeys = PrimaryKeys<TEntity>();
var properties = Properties(identifiers);
for (var i = 0; i < entities.Length; i++)
{
// build where condition for "identifiers"
var parameter = Expression.Parameter(typeof(TEntity));
var matches = properties.Select(p => Expression.Equal(
Expression.Property(parameter, p),
Expression.Constant(p.GetValue(entities[i]), p.PropertyType)));
var match = Expression.Lambda<Func<TEntity, bool>>(
matches.Aggregate((p, q) => Expression.AndAlso(p, q)),
parameter);
// match "identifiers" for current item
var current = context.Set<TEntity>().SingleOrDefault(match);
if (current != null)
{
// update primary keys
foreach (var k in primaryKeys)
k.SetValue(entities[i], k.GetValue(current));
// update all the values
context.Entry(current).CurrentValues.SetValues(entities[i]);
// replace updated item
entities[i] = current;
}
else
{
// add new item
entities[i] = context.Set<TEntity>().Add(entities[i]);
}
}
return entities;
}
private static PropertyInfo[] Properties<TEntity>(Expression<Func<TEntity, object>> identifiers)
where TEntity : class
{
// e => e.SomeValue
var direct = identifiers.Body as MemberExpression;
if (direct != null)
{
return new[] { (PropertyInfo)direct.Member };
}
// e => (object)e.SomeValue
var convert = identifiers.Body as UnaryExpression;
if (convert != null)
{
return new[] { (PropertyInfo)((MemberExpression)convert.Operand).Member };
}
// e => new { e.SomeValue, e.OtherValue }
var multiple = identifiers.Body as NewExpression;
if (multiple != null)
{
return multiple.Arguments
.Cast<MemberExpression>()
.Select(a => (PropertyInfo)a.Member)
.ToArray();
}
throw new NotSupportedException();
}
private static PropertyInfo[] PrimaryKeys<TEntity>()
where TEntity : class
{
return typeof(TEntity).GetProperties()
.Where(p => Attribute.IsDefined(p, typeof(KeyAttribute))
|| "Id".Equals(p.Name, StringComparison.Ordinal))
.ToArray();
}
}
}
以上是关于csharp 实现.AddOrUpdate也支持nullables的主要内容,如果未能解决你的问题,请参考以下文章
csharp [AddOrUpdate]あれば更新,なければ添加#ExtensionMethod
如何在 EF 4.3 中使用带有复杂键的 AddOrUpdate 播种数据
将 AddOrUpdate 与 Entity Framework 6 Repository 一起使用的单元测试方法