Как получить необработанные данные предварительного просмотра от объекта Camera по крайней мере 15 кадров в секунду в Android?

Вот как найти все измененные отношения «многие ко многим». Я реализовал код как методы расширения:

public static class IaExtensions
{
    public static IEnumerable<Tuple<object, object>> GetAddedRelationships(
        this DbContext context)
    {
        return GetRelationships(context, EntityState.Added, (e, i) => e.CurrentValues[i]);
    }

    public static IEnumerable<Tuple<object, object>> GetDeletedRelationships(
        this DbContext context)
    {
        return GetRelationships(context, EntityState.Deleted, (e, i) => e.OriginalValues[i]);
    }

    private static IEnumerable<Tuple<object, object>> GetRelationships(
        this DbContext context,
        EntityState relationshipState,
        Func<ObjectStateEntry, int, object> getValue)
    {
        context.ChangeTracker.DetectChanges();
        var objectContext = ((IObjectContextAdapter)context).ObjectContext;

        return objectContext
            .ObjectStateManager
            .GetObjectStateEntries(relationshipState)
            .Where(e => e.IsRelationship)
            .Select(
                e => Tuple.Create(
                    objectContext.GetObjectByKey((EntityKey)getValue(e, 0)),
                    objectContext.GetObjectByKey((EntityKey)getValue(e, 1))));
    }
}

Некоторое объяснение. Отношение «многие ко многим» представлено в EF как независимые ассоциации, или IA. Это связано с тем, что внешние ключи для отношений не отображаются нигде в объектной модели. В базе данных FK находятся в таблице соединений, и эта таблица соединений скрыта от объектной модели.

IA отслеживаются в EF, используя «записи отношений». Они похожи на объекты DbEntityEntry, которые вы получаете из DbContext.Entry, за исключением того, что они представляют собой взаимосвязь между двумя объектами, а не самим объектом. Записи взаимосвязей не отображаются в API-интерфейсе DbContext, поэтому вам необходимо перейти к ObjectContext для доступа к ним.

Новая запись отношения создается, когда создается новая связь между двумя объектами, например, путем добавления Сотрудник компании. Коллектив сотрудников. Это отношение находится в добавленном состоянии.

Аналогично, когда связь между двумя объектами удаляется, запись отношения помещается в состояние «Удалено».

Это означает, что для поиска измененного отношения «многие ко многим» (или фактически любые измененные IA), нам нужно найти добавленные и удаленные записи отношений. Это то, что делают GetAddedRelationships и GetDeletedRelationships.

Как только у нас есть записи отношений, нам нужно их понять. Для этого вам нужно знать кусочек инсайдерских знаний. Свойство CurrentValues ​​записи взаимозависимых (или неизмененных) отношений содержит два значения, которые являются объектами EntityKey объектов в обоих концах отношения. Аналогично, но немного раздражающе, свойство OriginalValues ​​записи «Удаленные отношения» содержит объекты EntityKey для объектов на обоих концах удаленной связи.

(И да, это ужасно.

Различие CurrentValues ​​/ OriginalValues ​​заключается в том, почему мы передаем делегат в закрытый метод GetRelationships.

Как только у нас есть объекты EntityKey, мы может использовать GetObjectByKey для получения фактических экземпляров сущностей. Мы возвращаем их как кортежи и там у вас есть.

Вот некоторые сущности, контекст и инициализатор, которые я использовал для проверки этого. (Примечание - тестирование не было обширным.)

public class Company
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Employee> Employees { get; set; }

    public override string ToString()
    {
        return "Company " + Name;
    }
}

public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Company> Companies { get; set; }

    public override string ToString()
    {
        return "Employee " + Name;
    }
}

public class DataContext : DbContext
{
    static DataContext()
    {
        Database.SetInitializer(new DataContextInitializer());
    }

    public DbSet<Company> Companies { get; set; }
    public DbSet<Employee> Employees { get; set; }

    public override int SaveChanges()
    {
        foreach (var relationship in this.GetAddedRelationships())
        {
            Console.WriteLine(
                "Relationship added between {0} and {1}",
                relationship.Item1,
                relationship.Item2);
        }

        foreach (var relationship in this.GetDeletedRelationships())
        {
            Console.WriteLine(
                "Relationship removed between {0} and {1}",
                relationship.Item1,
                relationship.Item2);
        }

        return base.SaveChanges();
    }

}

public class DataContextInitializer : DropCreateDatabaseAlways<DataContext>
{
    protected override void Seed(DataContext context)
    {
        var newMonics = new Company { Name = "NewMonics", Employees = new List<Employee>() };
        var microsoft = new Company { Name = "Microsoft", Employees = new List<Employee>() };

        var jim = new Employee { Name = "Jim" };
        var arthur = new Employee { Name = "Arthur" };
        var rowan = new Employee { Name = "Rowan" };

        newMonics.Employees.Add(jim);
        newMonics.Employees.Add(arthur);
        microsoft.Employees.Add(arthur);
        microsoft.Employees.Add(rowan);

        context.Companies.Add(newMonics);
        context.Companies.Add(microsoft);
    }
}

Вот пример его использования:

using (var context = new DataContext())
{
    var microsoft = context.Companies.Single(c => c.Name == "Microsoft");
    microsoft.Employees.Add(context.Employees.Single(e => e.Name == "Jim"));

    var newMonics = context.Companies.Single(c => c.Name == "NewMonics");
    newMonics.Employees.Remove(context.Employees.Single(e => e.Name == "Arthur"));

    context.SaveChanges();
} 
30
задан EricOops 17 October 2011 в 07:24
поделиться