/// <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); }