Esempio n. 1
0
        /// <summary>
        /// Converts a row from a <see cref="DataTable"/> into an <see cref="IEntity"/>
        /// that can be attached to the database
        /// </summary>
        /// <param name="row">Source data</param>
        /// <param name="context">Context to attach result to</param>
        /// <param name="type">CLR <see cref="Type"/> of the <see cref="IEntity"/></param>
        /// <param name="infos">Properties which map to <see cref="DataColumn"/>s in the <see cref="DataRow"/></param>
        public static IEntity ToEntity(this DataRow row, IRemsDbContext context, Type type, PropertyInfo[] infos)
        {
            IEntity entity = Activator.CreateInstance(type) as IEntity;

            foreach (var info in infos)
            {
                object value = row[info.Name];

                // Use default value if cell is empty
                if (value is DBNull || value is "")
                {
                    continue;
                }

                var itype = info.PropertyType;

                // If the property is an entity, find or create the matching entity
                if (typeof(IEntity).IsAssignableFrom(itype))
                {
                    value = context.FindMatchingEntity(itype, value) ?? context.CreateEntity(itype, value);
                }
                else
                {
                    // If the value is nullable, convert its type
                    value = Convert.ChangeType(value, Nullable.GetUnderlyingType(itype) ?? itype);
                }

                info.SetValue(entity, value);
            }

            return(entity);
        }
        /// <summary>
        /// Find the properties on an entity that contain data
        /// </summary>
        public static IEnumerable <PropertyInfo> GetEntityProperties(this IRemsDbContext context, Type type)
        {
            // All the primary and foreign keys for an entity
            var entity = context.Model.GetEntityTypes()
                         .First(e => e.ClrType == type);

            var primaries = entity
                            .FindPrimaryKey()
                            .Properties
                            .Select(p => p.PropertyInfo);

            var foreigns = entity
                           .GetForeignKeys()
                           .SelectMany(k => k.Properties.Select(p => p.PropertyInfo));

            // All the non-primary fields of an entity
            var props = type
                        .GetProperties()
                        .Where(p => !p.PropertyType.IsGenericType)
                        .Where(p => p.PropertyType.IsValueType || p.PropertyType.IsInstanceOfType(""))
                        .Except(primaries)
                        .Except(foreigns);

            return(props);
        }
        /// <summary>
        /// Gets all the soil layers from a given experiment
        /// </summary>
        internal static SoilLayer[] GetSoilLayers(this IRemsDbContext context, int experimentId)
        {
            var soil = context.Experiments.Find(experimentId).Field.Soil;

            var layers = context.SoilLayers
                         .Where(s => s.SoilId == soil.SoilId)
                         .OrderBy(l => l.FromDepth)
                         .ToArray();

            return(layers);
        }
        /// <summary>
        /// Search the context for the first entity of the given type which has a property that matches
        /// the given value
        /// </summary>
        /// <remarks>
        /// This is intended to be used to find related entities by name
        /// </remarks>
        public static IEntity FindMatchingEntity(this IRemsDbContext context, Type type, object value)
        {
            var set = context.GetType()
                      .GetMethod("GetSet")
                      .MakeGenericMethod(type)
                      .Invoke(context, new object[0])
                      as IEnumerable <IEntity>;

            var infos = type.GetProperties();
            var test  = value.ToString().ToLower();

            return(set.FirstOrDefault(e => infos.Any(i => i.GetValue(e)?.ToString().ToLower() == test)));
        }
        /// <summary>
        /// Searches the context for a trait that matches the given name, creating one if none are found
        /// </summary>
        internal static Trait GetTraitByName(this IRemsDbContext context, string name)
        {
            var trait = context.Traits.ToArray().FirstOrDefault(t => t.NameMatches(name));

            if (trait is null)
            {
                trait = new Trait()
                {
                    Name = name
                };
                context.Add(trait);
            }

            context.SaveChanges();
            return(trait);
        }
        internal static IEnumerable <Plot> FindPlots(this IRemsDbContext context, object content, Experiment experiment)
        {
            // Find all the plots in the experiment
            var plots = context.Plots.Where(p => p.Treatment.Experiment == experiment);

            var text = content.ToString().ToLower();

            if (text == "all" || text == "avg")
            {
                return(plots);
            }

            var ids = text.Split(',').Select(i => Convert.ToInt32(i));

            return(plots.Where(p => ids.Contains(p.Column.GetValueOrDefault())));
        }
        /// <summary>
        /// Add a measurement to the context, overwriting the value if a matching entry already exists
        /// </summary>
        public static void InsertData <T>(this IRemsDbContext context, Expression <Func <T, bool> > comparer, T data, double value)
            where T : class, IEntity, IValue
        {
            var set   = context.GetSet <T>();
            var found = set
                        .Where(comparer)
                        .SingleOrDefault();

            if (found != null)
            {
                found.Value = value;
            }
            else
            {
                set.Attach(data);
            }
        }
        /// <summary>
        /// Create an entity of the given type, and attach it to the database after attempting to assign
        /// one of its properties the given value
        /// </summary>
        /// <param name="context">The context to attach the entity to</param>
        /// <param name="type">The CLR type of the <see cref="IEntity"/></param>
        /// <param name="value">The value to attempt to assign</param>
        /// <returns></returns>
        public static IEntity CreateEntity(this IRemsDbContext context, Type type, object value)
        {
            IEntity entity = Activator.CreateInstance(type) as IEntity;
            var     name   = type.GetProperty("Name");

            if (name is null)
            {
                type.GetProperty("SoilType")?.SetValue(entity, value);
            }
            else
            {
                name?.SetValue(entity, value);
            }

            context.Attach(entity);
            context.SaveChanges();

            return(entity);
        }
        /// <summary>
        /// Attempts to find a database trait which matches the columns in a data table
        /// </summary>
        /// <param name="context">The database context to search</param>
        /// <param name="table">The table containing the columns</param>
        /// <param name="skip">The number of initial columns to skip</param>
        /// <param name="type">The trait type</param>
        /// <returns></returns>
        internal static Trait[] GetTraitsFromColumns(this IRemsDbContext context, DataTable table, int skip, string type)
        {
            Trait getTrait(DataColumn c)
            {
                var trait = context.Traits.FirstOrDefault(t => t.Name.ToLower() == c.ColumnName.ToLower());

                if (trait is null)
                {
                    trait = context.AddTrait(c.ColumnName, type);
                }

                return(trait);
            }

            return(table.Columns.Cast <DataColumn>()
                   .Skip(skip)
                   .Select(c => getTrait(c))
                   .ToArray());
        }
        /// <summary>
        /// Adds a trait to the database
        /// </summary>
        /// <param name="name">Trait name</param>
        /// <param name="type">Trait type</param>
        /// <returns></returns>
        internal static Trait AddTrait(this IRemsDbContext context, string name, string type)
        {
            var unit = context.Units.FirstOrDefault(u => u.Name == "-");

            if (unit is null)
            {
                unit = new Domain.Entities.Unit()
                {
                    Name = "-"
                }
            }
            ;

            var trait = new Trait()
            {
                Name = name,
                Type = type,
                Unit = unit
            };

            context.Add(trait);
            context.SaveChanges();
            return(trait);
        }