Ад атрибутов C # - один класс, совместно используемый мобильным устройством и сервером на двух разных платформах SQL

Мы разделяем одно поко с

  • ServiceStack WebServices
  • ServiceStack Orm с MySQL
  • Мобильный клиент Xamarin, использующий Sqlite.net.

Проблема в том, что общие классы превратились в беспорядок.

        [PrimaryKey, AutoIncrement]
        public int Id { get; set; }
#if __MOBILE__
        [Indexed]
#else
        [Index]
#endif
        public string UserAccountId { get; set; }
#if __MOBILE__
        [Indexed]
#else
        [Index]
#endif

И если это уже не так плохо, мне нужно

  • Ограничьте длину каждого поля в базе данных ....
  • Сохраните эти объекты в MongoDb. К счастью, у них есть класс AutoMapper, который делает это во время выполнения.

Не знаю, что делать. Мои неудачные идеи включают в себя:

  • Попробуйте использовать: [Conditional ("DEBUG")]. Но это ничего не делает для этого

  • Похоже, что sqlite.net использует свой собственный атрибут

    [AttributeUsage (AttributeTargets.Property)] открытый класс IndexedAttribute: Attribute

    Таким образом, он не найдет атрибут Mysql [Index]

  • Можно попробовать включить два атрибута в каждое свойство

    [Индексировано] [Индексируется] общедоступная строка UserAccountId {get; набор; }

  • Я попытался превратить его в две однострочные, но С # VS жалуется

#if __MOBILE__ [Indexed]  #endif 
#if __MOBILE__ [Index]    #endif

В конце концов, единственный подход, при котором ** APPEARS ** будет работать, - это просто сохранить интерфейс как единственное определение класса и иметь много конкретных классов, которые будут декорированы по-разному.

Любые идеи??


person mbalsam    schedule 22.12.2017    source источник
comment
Это не POCO, если у вас есть все эти атрибуты. Вероятно, сильная сторона в пользу использования беглого построителя моделей, а не атрибутов.   -  person mason    schedule 22.12.2017
comment
Ваше право, это не поко. В: Я предполагаю, что мне нужно будет создать класс ModelBuilder самому. Есть ли какая-то структура общего назначения, которую я мог бы использовать в качестве наложения? Я предполагаю, что тот, что находится в EntityFramework, не будет работать.   -  person mbalsam    schedule 22.12.2017
comment
Я не знаком с ServiceStack.OrmLite, поэтому, к сожалению, не знаю, какие у вас есть варианты.   -  person mason    schedule 22.12.2017
comment
Очевидно, мы можем сохранить оба определения. Итак, этот синтаксис действителен [Indexed, Index] публичная строка UserAccountId   -  person mbalsam    schedule 22.12.2017


Ответы (4)


Если бы вы создавали свой код в соответствии с «чистой архитектурой» дяди Боба, вы бы не пытались создать единое представление, которое можно было бы использовать для многих различных целей, поскольку это заставляет ваши зависимости указывать наружу от политики высокого уровня к внешним кругам.

Чистая архитектура

Источник: https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-architecture.html

Фактически, вы могли бы поместить Entity в центральный круг вместе с бизнес-правилами предприятия, но DTO, который вы используете для хранения / извлечения данных для конкретной базы данных, должен быть исключен из ваших «фреймворков и драйверов». круг.

Все эти специфичные для базы данных атрибуты принадлежат DTO в синем кружке, а не объектам в центре.

person Fenton    schedule 22.12.2017
comment
Итак, в основном мой последний выбор, сохранить и интерфейс и несколько конкретных классов для каждой реализации. Я собираюсь предоставить образец ниже. - person mbalsam; 22.12.2017

Итак, предложение дяди Боба и Фентона - мой последний выбор. Внесите изменения в Интерфейс.

Я буду использовать Re-Sharper для обновления всех классов классов ..

Это должно сработать.

namespace Evaluation.Entitys
{
    public interface IUserEntity
    {
        string UserAccountId { get; set; }
    }

    public class UserEntity : IUserEntity
    {
        public string UserAccountId { get; set; }

        public UserEntity()
        {

        }
    }

    public class UserEntityTransport : IUserEntity
    {
        public string UserAccountId { get; set; }

        public UserEntityTransport(IUserEntity e)
        {
            UserAccountId = e.UserAccountId;
        }
    }
}
#if __MOBILE__

namespace Evaluation.Moible 
{


    using SQLite;
    using SQLite.Net;
    public class UserEntityMobileDB : IUserEntity
    {
        [Index]
        public string UserAccountId { get; set; }
        public UserEntityMobileDB(IUserEntity e)
        {
            UserAccountId = e.UserAccountId;
        }
    }
}
#endif

#if __WIN32__
namespace Evaluation.Server
{
    using Evaluation.Entitys;
    using ServiceStack.DataAnnotations;
    using SQLite;

    public class UserEntityServerDB : IUserEntity
    {
        [Indexed]
        public string UserAccountId { get; set; }

        public UserEntityServerDB(IUserEntity e)
        {
            UserAccountId = e.UserAccountId;

        }
    }
}
#endif 

Это должно сработать.

Недостатки

  1. Необходимо поддерживать несколько конструкторов 4-кратного копирования на уровне контроллера.
  2. Один класс теперь 4 класса.
person mbalsam    schedule 22.12.2017

Мейсон предложил бы создать такой же беглый инструмент, как Построитель моделей. Так как этого в настоящее время не существует ??? в ServiceStack.OrmLine и SqlLite.net, я полагаю, мне придется его построить.

Я нашел этот образец кода из entity framework.

modelBuilder 
    .Entity<Person>() 
    .Property(t => t.Name) 
    .HasColumnAnnotation( 
        "Index",  
        new IndexAnnotation(new IndexAttribute("IX_Name") { IsUnique = true }));

Моя версия псудокода будет выглядеть так:

modelBuilder 
    .Entity<UserEntity>() 
    .Property(t => t.UserAccountId) 
    .AddColumnIndex(new IndexAnnotation(new IndexAttribute("IX_Name") {});
person mbalsam    schedule 22.12.2017

По-видимому, этот синтаксис действителен и тоже должен работать.

using SQLite;
using ORMLite = ServiceStack.DataAnnotations;

[ORMLite.PrimaryKey, ORMLite.AutoIncrement]
[SQLite.PrimaryKey, SQLite.AutoIncrement]
public int Id { get; set; }

[Indexed,Index]
public string UserAccountId { get; set; }
person mbalsam    schedule 22.12.2017