Есть ли общий способ проверки, если запись дублируется?Это должно быть проверено уникальным ограничением в базе данных - PullRequest
1 голос
/ 28 марта 2019

У меня есть объекты, сгенерированные из базы данных. Я загружаю данные из Excel и импортирую их построчно в базу данных. Я установил уникальное ограничение на таблицу, чтобы оно не допускало дублирования. Перед добавлением новой записи в БД я хочу проверить, существует ли такая запись уже не по идентификатору, а по свойствам, которые соответствуют уникальному ограничению.

Я могу проверить это, выполнив Switch Case и введя все возможные варианты. Я хочу, чтобы это было общим, но я не знаю как. Вот как я это сделал до сих пор:

(Объект является экземпляром класса Entity и имеет некоторые свойства, заполненные данными)

var entityDuplicate = db.Entity.SingleOrDefault(f => f.Name == object.Name && f.Surname == object.Surname);
if(entityDuplicate == null)
{
    db.Entity.Add(object);
}

Это работает, но могу ли я сделать этот общий способ? так что мне не нужно вводить все вручную? Подобно уникальному ограничению chceck в SQL и проверьте, есть ли в таблице такая запись.

Ответы [ 3 ]

1 голос
/ 28 марта 2019

Чтобы иметь общий способ, вам нужно сгенерировать f => f.Name == object.Name && f.Surname == object.Surname

Это можно сделать с помощью Linq.Expression.Вы можете начать с определения своего пользовательского атрибута:

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public sealed class MustBeUniqueAttribute : Attribute { }

Теперь в классе вы хотите вставить отметку для всех свойств, которые должны участвовать в сравнении с этим атрибутом:

public class Entity
{
    public Guid Id { get; set; }

    [MustBeUnique]
    public string Name { get; set; }

    [MustBeUnique]
    public string Surname { get; set; }
}

Теперь вы можетесгенерировать лямбда-выражение:

public static Expression<Func<T, bool>> CreatExpression<T>(T toInsert)
{
    var type = typeof(T);
    var membersToTrack = type.GetMembers(
        BindingFlags.GetField
        | BindingFlags.GetProperty
        | BindingFlags.Instance
        | BindingFlags.Public)
        .Where(m => m.CustomAttributes.Any(a => a.AttributeType == typeof(MustBeUniqueAttribute)))
        .ToArray();

    var parameter = Expression.Parameter(type, "x");
    if (membersToTrack.Length == 0)
        return Expression.Lambda<Func<T, bool>>(Expression.Constant(false), parameter);

    Expression body = null;
    foreach (var member in membersToTrack)
    {
        object actualValue = null;
        if (member is PropertyInfo info)
            actualValue = info.GetValue(toInsert);
        else
            actualValue = ((FieldInfo) member).GetValue(toInsert);

        var leftExpression = Expression.PropertyOrField(parameter, member.Name);
        var rightExpression= Expression.Constant(actualValue);
        var equalExpression = Expression.Equal(leftExpression, rightExpression);

        body = body == null ? equalExpression : Expression.AndAlso(body, equalExpression);
    }

    var lambda = Expression.Lambda<Func<T, bool>>(body, parameter);
    return lambda;
}

Использование:

var objectToInsert = // import from Excel
var expression = CreatExpression(objectToInsert);

var entityDuplicate = db.Entity.SingleOrDefault(expression);
if(entityDuplicate == null)
{
    db.Entity.Add(object);
}

РЕДАКТИРОВАТЬ:

Вы можете проверить это онлайн

0 голосов
/ 28 марта 2019

Вы можете сделать это на одной записи или на множестве записей, используя кроме Linq. Создайте словарь записей из базы данных и словарь записей из файла excel. В этом примере вместо Excel используется json, но концепция та же.

`Dictionary<string, string> listProdOnDb = new Dictionary<string, string>();`
`Dictionary<string, string> listProdJson = new Dictionary<string, string>();

foreach (var item in ListaProdJson)
        {
            listProdJson.Add(item.codProdotto.Trim(), item.descrizione.Trim());
        }
strSql = "SELECT Cod_Prod_Rpt,Des_Prod_Rpt FROM xxxx Where xxxxx = xxx";
  using (SqlCommand command = new SqlCommand(strSql, connection))
            {
            using (SqlDataReader sdr = command.ExecuteReader())
                {
                string[] col = { "", "" };
                while (sdr.Read())
                    {
                    if (!sdr.IsDBNull(0))
                        col[0] = sdr.GetString(0).Trim();

                    if (!sdr.IsDBNull(1))
                        col[1] = sdr.GetString(1).Trim();

                    // add items
                    if (col[0] != "") // check if key is valid
                        listProdOnDb.Add(col[0], col[1]);
                }

                }
            }

 IEnumerable<string> onlyInFirstSet = listProdJson.Keys.Except(listProdOnDb.Keys);
 if(onlyInFirstSet.Count() > 0) {
.....
 }

`

0 голосов
/ 28 марта 2019

То, что вы хотите, это универсальный метод, чтобы увидеть, существует запись объекта или нет.Вы можете использовать метод Any () класса DBSet и передать ему условие для поиска записи.

public bool CheckIfEntityExistsByEntityId<T>(Expression<Func<T,bool>> expr)
{
    return _baseRepository.DbSet().Any(u => expr);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...