Строительство данных договор интерфейса, который может быть использован в сущности рамок 4.1 для обеспечения субъекта действия


Мне нужны некоторые мысли о подходе коллега и я с рамками субъекта. В принципе, в реальности представлены контракты. Эти договоры хранения набора бизнес-правил, поэтому, когда они, наконец, сохраняются, мы знаем, что они являются действительными. Мы также можем проверить действительность от рамок компании, но это не так важно. Поскольку EF требует от вас, чтобы не иметь параметризованный конструктор, мы не передаем фактические сущности в EF, но, скорее, договор, который представляет ее.

Итак, как это работает, впервые создан контекст. Далее, мы создаем контракт, а затем создать домен объект, передав его по договору. Внутри конструктора сущности вызова IsValid метод выполнен. Это проходит через все правила бизнеса. Если кто-либо не удается, в сущности, считается недействительным и исключение какого-то бросается. Если он действителен, то тогда добавьте контракта на контекст и сохранить изменения и переходим обратно в сущности. Вот некоторый код, который демонстрирует идею:

    /// <summary>
    /// Interface the all Contracts will impelement
    /// </summary>
    public interface IEntityContract
    {
        bool IsValid();
    }

    /// <summary>
    /// Business Rule Loigc
    /// </summary>
    public class BusinessRule<TEntity> where TEntity: IEntityContract
    {
        //Logic to handle business rules
    }


    /// <summary>
    /// Abstract class that represents a Base Contract
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public abstract class EntityContract<TEntity>: IEntityContract where TEntity: IEntityContract
    {

        private readonly List<BusinessRule<TEntity>> _businessRules = new List<BusinessRule<TEntity>>();

        public bool IsValid()
        {
            var entityIsValid = true;
            foreach (var businessRule in _businessRules)
            {
                //IF any rule fails the entityIsValid = fale
            }

            return entityIsValid;
        }


        protected void RegisterBusinessRule(BusinessRule<TEntity> rule)
        {
            _businessRules.Add(rule);
        }
    }

    public interface IUserContract: IEntityContract
    {
        string UserName { get; set; }
        string Password { get; set; }
    }

    internal sealed class UserContract: EntityContract<IUserContract>, IUserContract
    {

        public UserContract()
        {
            this.RegisterBusinessRule(new BusinessRule<IUserContract>());
            this.RegisterBusinessRule(new BusinessRule<IUserContract>());
        }

        public string UserName { get; set; }
        public string Password { get; set; }
    }

    /// <summary>
    /// Abstract class the represetn a base domain entity
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public abstract class EntityBase<TEntity> where TEntity: IEntityContract
    {
        protected EntityBase(TEntity contract)
        {
            if(!contract.IsValid())
            {
                throw new Exception("Business Rule Violation");
            }
        }

        public Guid Id { get; set; }
        protected void BuildProperties()
        {
            //This method will iterate the TEntity properties from the contract and build the actual domain entity
        }

    }

    /// <summary>
    /// Class that represent a domain entity
    /// </summary>
    public class User: EntityBase<IUserContract>
    {
        public User(IUserContract contract) : base(contract)
        {
            this.BuildProperties();
        }
    }

    //Domonstration of idea
    public class TestClass
    {
        public void TestUserEnity()
        {

            //Using Entity Framework 4.1 we instantiate a DbContext
            var dataContext = new SomeEntityFrameworkDbContext();

            //Create the UserContract
            var userContract = new UserContract {UserName = "someUserName@place.com", Password = "thePassword"};
            try
            {
                //Create a new user and pass it the UserContract
                var user = new User(userContract);

                //If evertyhing goes ok, add the new eneity to the context
                dataContext.Add(userContract);

                //Persist the data
                dataContext.SaveChanges();
            }
            catch (Exception)
            {

                //throw the excpetion and send back the failures
            }

        }
    }


3518
15
задан 17 мая 2011 в 12:05 Источник Поделиться
Комментарии
2 ответа

Учитывая рамки сущности не как параметризованные конструкторы, я думаю, что единственное решение состоит в том, когда объект будет прикреплен к контексту или на метод SaveChanges оценивать сущность.

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

public class User
{
public string Username { get; set; }
public string Password { get; set; }
}

public interface IRepository<TEntity> where TEntity : class
{
void Create(TEntity entity);
void Update(TEntity entity);
void Delete(TEntity entity);
}

public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
private readonly IEntityContract<TEntity> _contract;
private readonly DbContext _context;

public Repository(IEntityContract<TEntity> contract, DbContext context)
{
_contract = contract;
_context = context;
}

public void Create(TEntity entity)
{
//beofre we try to create it, lets evaluate it
if (!_contract.IsValid(entity))
{
//possibly throw an exception or let the client know there was an issue.
}

//Now implement your create code.
_context.Add(entity);
_context.SaveChanges();
}

public void Update(TEntity entity)
{
//beofre we try to update it, lets evaluate it
if (!_contract.IsValid(entity))
{
//possibly throw an exception or let the client know there was an issue.
}

//Now implement your update code.
_context.Attach(entity);
_context.SaveChanges();
}

public void Delete(TEntity entity)
{
//delete code
}
}

/// <summary>
/// Interface the all Contracts will impelement
/// </summary>
public interface IEntityContract<TEntity> where TEntity: class
{
bool IsValid(TEntity entity);
void RegisterBusinessRule(BusinessRule<TEntity> rule);
IList<BusinessRule<TEntity>> Rules { get; set; }
}

/// <summary>
/// Business Rule Loigc
/// </summary>
public class BusinessRule<TEntity> where TEntity : class
{
//Logic to handle business rules
}

/// <summary>
/// Abstract class that represents a Base Contract
/// </summary>
/// <typeparam name="TEntity"></typeparam>
public abstract class EntityContract<TEntity> : IEntityContract<TEntity> where TEntity : class
{

protected EntityContract()
{
Rules = new List<BusinessRule<TEntity>>();
}

protected EntityContract(IList<BusinessRule<TEntity>> rules)
{
Rules = rules;
}

public virtual bool IsValid(TEntity entity)
{
var entityIsValid = true;
foreach (var businessRule in Rules)
{
//IF any rule fails the entityIsValid = false
}

return entityIsValid;
}

public IList<BusinessRule<TEntity>> Rules { get; set; }

public void RegisterBusinessRule(BusinessRule<TEntity> rule)
{
Rules.Add(rule);
}

}

public interface IUserContract : IEntityContract<User>
{

}

public class UserContract : EntityContract<User>, IUserContract
{

}

//Domonstration of idea
public class TestClass
{
public void TestUserEntity()
{

//Using Entity Framework 4.1 we instantiate a DbContext
var dataContext = new SomeEntityFrameworkDbContext();

var respository = new Repository<User>(new UserContract(), dataContext);
//Create the UserContract

var user = new User()
{
Password = "123456",
Username = "me@domain.com"
};

try
{
respository.Create(user);
}
catch (Exception ex)
{

//lets assume an excpetion gets thrown if the IsVlaid fails.
}

}
}

Как вы можете видеть, сейчас мы берем на себя ответственность оценки сущности от самой сущности. Который, я чувствую, лучше держать лицо в чистоте и оставить какой-либо логики из сущности. Это, как я чувствую себя в последние пару лет.

6
ответ дан 20 ноября 2013 в 02:11 Источник Поделиться

ваш IUserContract наследует IEntityContract но не реализовать боол метода IsValid(); метод, я всегда считал, что если вы наследуют интерфейс, который вы должны реализовать все, что внутри этого интерфейса.

это единственное, что я вижу, что выглядит неуместно.

Редактировать

как Retailcoder указал, что последний наследует интерфейс придется все реализовать во всех интерфейсах в цепи. это означает, что внутри внутреннего запечатанного класса UserContract должна быть реализация боол метода IsValid(); метод, которого нет.

Абстрактный класс EntityBase также отсутствует боол метода IsValid(); метод


Слили ответить

Имея интерфейс, который делает только одну вещь не кажется правильным для меня.

кстати, что вы настроили ваш класс пользователя в ваш ответ гораздо лучше, чем интерфейс, который заставляет вас создавать учетные данные пользователя. Мне нравится это намного лучше.

Мне тоже нравится новый IEntityContract как его силы больше, чем просто функция IsValid метод. похоже, в нем больше логики, которая нужна для других вещей, которые будут вынуждены в той или иной мере, уменьшение количества интерфейсов и в итоге код.

Мне нравится новый дизайн и структуру, которую вы предоставили в своем ответе, кажется, намного четче и более читабельным.

Я знаю, что это комментарий на комментарий, но видя, как ОП является то, что разместил комментарий, который я рассматриваю (все-таки возвращаясь к исходному комментарий) Я думаю, что этот ответ остается в силе.

3
ответ дан 19 ноября 2013 в 04:11 Источник Поделиться