Exemple #1
0
        private static async Task <TEntity> GetOrCreateEntityAsync <TEntity>(NesteoDbContext dbContext, Expression <Func <TEntity, bool> > predicate,
                                                                             Func <TEntity> factoryFunc) where TEntity : class
        {
            // Get db set
            DbSet <TEntity> dbSet = dbContext.Set <TEntity>();

            // If the entity exists in the local snapshot, return it directly
            TEntity entity = dbSet.Local.FirstOrDefault(predicate.Compile());

            if (entity != null)
            {
                return(entity);
            }

            // Search the entity in the database
            entity = await dbSet.FirstOrDefaultAsync(predicate).ConfigureAwait(false);

            if (entity != null)
            {
                return(entity);
            }

            // Entity doesn't exist yet. Create a new one
            entity = factoryFunc.Invoke();
            return(dbSet.Add(entity).Entity);
        }
Exemple #2
0
 public RegionService(NesteoDbContext dbContext, IMapper mapper) : base(dbContext, mapper)
 {
 }
Exemple #3
0
 public NestingBoxService(NesteoDbContext dbContext, IMapper mapper, INestingBoxIdGenerator nestingBoxIdGenerator) : base(dbContext, mapper)
 {
     _nestingBoxIdGenerator = nestingBoxIdGenerator ?? throw new ArgumentNullException(nameof(nestingBoxIdGenerator));
 }
Exemple #4
0
 public OwnerService(NesteoDbContext dbContext, IMapper mapper) : base(dbContext, mapper)
 {
 }
Exemple #5
0
        private static async Task <int> ImportCsvFileAsync <TRecord>(NesteoDbContext dbContext, string filePath)
        {
            using var fileReader = new StreamReader(filePath);
            using var csvReader  = new CsvReader(fileReader);

            // File is expected to have a header
            csvReader.Configuration.HasHeaderRecord = true;

            // Set field delimiter
            csvReader.Configuration.Delimiter = ",";

            // Don't throw errors when fields are empty/missing.
            csvReader.Configuration.MissingFieldFound = null;

            // Match header names case insensitively
            csvReader.Configuration.PrepareHeaderForMatch = (header, index) => header.ToLower();

            // Validate header
            Console.WriteLine("Validating file header...");
            csvReader.Read();
            csvReader.ReadHeader();
            csvReader.ValidateHeader <TRecord>();

            Console.WriteLine($"Importing data from {filePath} ...");

            var exceptions     = 0;
            var fileLineNumber = 1;

            foreach (TRecord record in csvReader.GetRecords <TRecord>())
            {
                fileLineNumber++;
                Console.WriteLine($"Importing line {fileLineNumber}: {record.GetType().Name} {{{Utils.SerializeObjectProperties(record)}}}");

                try
                {
                    switch (record)
                    {
                    case NestingBoxRecord nestingBoxRecord:
                        await ImportNestingBoxRecordAsync(dbContext, nestingBoxRecord).ConfigureAwait(false);

                        break;

                    case InspectionRecord inspectionRecord:
                        await ImportInspectionRecordAsync(dbContext, inspectionRecord).ConfigureAwait(false);

                        break;

                    default: throw new InvalidOperationException($"Unexpected record type: {record.GetType()}");
                    }
                }
                catch (Exception ex)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine($"  !! Import failed: {ex.Message}");
                    Console.ResetColor();
                    exceptions++;
                }
            }

            return(exceptions);
        }
Exemple #6
0
 private static async Task SaveDatabaseAsync(NesteoDbContext dbContext)
 {
     Console.WriteLine("Saving changes to database...");
     await dbContext.SaveChangesAsync().ConfigureAwait(false);
 }
Exemple #7
0
        private static async Task ImportInspectionRecordAsync(NesteoDbContext dbContext, InspectionRecord inspectionRecord)
        {
            // Create collection for comments
            var comments = new List <string>();

            if (!string.IsNullOrWhiteSpace(inspectionRecord.Comments))
            {
                comments.AddRange(inspectionRecord.Comments.Split(',').Select(c => c.Trim()).Where(c => !string.IsNullOrEmpty(c)));
            }

            // Get nesting box entity
            NestingBoxEntity nestingBoxEntity = await dbContext.NestingBoxes.FindAsync(inspectionRecord.NestingBoxId).ConfigureAwait(false);

            if (nestingBoxEntity == null)
            {
                throw new InvalidCsvRecordException($"Nesting box {inspectionRecord.NestingBoxId} doesn't exist.");
            }

            // Ensure the species entity exists
            SpeciesEntity speciesEntity = null;

            if (!string.IsNullOrWhiteSpace(inspectionRecord.SpeciesName) &&
                !new[] { "unbestimmt", "unbekannt" }.Contains(inspectionRecord.SpeciesName.ToLower()))
            {
                speciesEntity = await GetOrCreateEntityAsync(dbContext, species => species.Name == inspectionRecord.SpeciesName,
                                                             () => new SpeciesEntity { Name = inspectionRecord.SpeciesName }).ConfigureAwait(false);
            }

            // Analyze date info
            DateTime inspectionDate = string.IsNullOrWhiteSpace(inspectionRecord.Date)
                ? throw new InvalidCsvRecordException("Inspection date not set.")
                : ParseDate(inspectionRecord.Date);

            // Map nesting box condition
            (Condition condition, bool justRepaired) = GetCondition(inspectionRecord.Condition);
            if (condition != Condition.Good)
            {
                comments.Add($"Kasten-Zustand: {inspectionRecord.Condition}");
            }

            // Analyze ringing activity
            (ParentBirdDiscovery femaleParentBirdDiscovery, ParentBirdDiscovery maleParentBirdDiscovery, int ringedChickCount) =
                AnalyzeRingingActivity(inspectionRecord.RingedCount);

            // Create inspection
            dbContext.Inspections.Add(new InspectionEntity {
                NestingBox                = nestingBoxEntity,
                InspectionDate            = inspectionDate,
                InspectedByUser           = null,
                HasBeenCleaned            = GetYesNo(inspectionRecord.HasBeenCleaned),
                Condition                 = condition,
                JustRepaired              = justRepaired,
                Occupied                  = GetYesNoWithUnknown(inspectionRecord.Occupied),
                ContainsEggs              = !string.IsNullOrWhiteSpace(inspectionRecord.EggCount),
                EggCount                  = ParseNumberWithUnknown(inspectionRecord.EggCount),
                ChickCount                = ParseNumberWithUnknown(inspectionRecord.ChickCount),
                RingedChickCount          = ringedChickCount,
                AgeInDays                 = ParseNumberWithUnknown(inspectionRecord.ChickAges),
                FemaleParentBirdDiscovery = femaleParentBirdDiscovery,
                MaleParentBirdDiscovery   = maleParentBirdDiscovery,
                Species       = speciesEntity,
                ImageFileName = null,
                Comment       = comments.Any() ? string.Join(", ", comments) : null,
                LastUpdated   = inspectionDate
            });
        }
Exemple #8
0
        private static async Task ImportNestingBoxRecordAsync(NesteoDbContext dbContext, NestingBoxRecord nestingBoxRecord)
        {
            // Check id length
            if (nestingBoxRecord.Id.Length != 6)
            {
                throw new InvalidCsvRecordException("Id length is invalid. Expected 6 characters.");
            }

            // Ensure the nesting box doesn't exist yet
            if (await dbContext.NestingBoxes.FindAsync(nestingBoxRecord.Id).ConfigureAwait(false) != null)
            {
                throw new InvalidCsvRecordException("Nesting box exists and should not be overwritten.");
            }

            // Create collection for comments
            var comments = new List <string>();

            if (!string.IsNullOrWhiteSpace(nestingBoxRecord.Comments))
            {
                comments.AddRange(nestingBoxRecord.Comments.Split(',').Select(c => c.Trim()).Where(c => !string.IsNullOrEmpty(c)));
            }

            // Ensure the owner entity exists
            OwnerEntity ownerEntity = await GetOrCreateEntityAsync(dbContext, owner => owner.Name == nestingBoxRecord.OwnerName,
                                                                   () => new OwnerEntity { Name = nestingBoxRecord.OwnerName }).ConfigureAwait(false);

            // Ensure the region entity exists
            string regionName = $"{nestingBoxRecord.RegionCityName} - {nestingBoxRecord.RegionDetailedName}";

            string ExtractIdPrefix() => nestingBoxRecord.Id[0].ToString();

            RegionEntity regionEntity = await GetOrCreateEntityAsync(dbContext, region => region.Name == regionName,
                                                                     () => new RegionEntity { Name = regionName, NestingBoxIdPrefix = ExtractIdPrefix() }).ConfigureAwait(false);

            // Map material type
            var material = Material.Other;

            if (!string.IsNullOrWhiteSpace(nestingBoxRecord.Material))
            {
                material = GetMaterial(nestingBoxRecord.Material);
                if (material == Material.Other)
                {
                    comments.Add($"Material: {nestingBoxRecord.Material}");
                }
            }

            // Map hole size
            var holeSize = HoleSize.Other;

            if (!string.IsNullOrWhiteSpace(nestingBoxRecord.HoleSize))
            {
                holeSize = GetHoleSize(nestingBoxRecord.HoleSize);
                if (holeSize == HoleSize.Other)
                {
                    comments.Add($"Lochgröße: {nestingBoxRecord.HoleSize}");
                }
            }

            // Convert UTM to decimal coordinates
            Coordinate coordinate = null;

            if (!string.IsNullOrWhiteSpace(nestingBoxRecord.UtmEast) && !string.IsNullOrWhiteSpace(nestingBoxRecord.UtmNorth))
            {
                var utm = new UniversalTransverseMercator(UtmLatZ, UtmLongZ, double.Parse(nestingBoxRecord.UtmEast), double.Parse(nestingBoxRecord.UtmNorth));
                coordinate = UniversalTransverseMercator.ConvertUTMtoLatLong(utm);
            }

            // Analyze date info
            DateTime?hangUpDate = null;

            if (!string.IsNullOrWhiteSpace(nestingBoxRecord.HangUpDate))
            {
                hangUpDate = ParseDate(nestingBoxRecord.HangUpDate);
                if (hangUpDate.Value.Date == new DateTime(1999, 1, 1))
                {
                    hangUpDate = null;
                }
            }

            // Create nesting box
            dbContext.NestingBoxes.Add(new NestingBoxEntity {
                Id                  = nestingBoxRecord.Id,
                Region              = regionEntity,
                OldId               = null,
                ForeignId           = string.IsNullOrWhiteSpace(nestingBoxRecord.ForeignId) ? null : nestingBoxRecord.ForeignId,
                CoordinateLongitude = coordinate?.Longitude.DecimalDegree,
                CoordinateLatitude  = coordinate?.Latitude.DecimalDegree,
                HangUpDate          = hangUpDate,
                HangUpUser          = null,
                Owner               = ownerEntity,
                Material            = material,
                HoleSize            = holeSize,
                ImageFileName       = null,
                Comment             = comments.Any() ? string.Join(", ", comments) : null,
                LastUpdated         = string.IsNullOrWhiteSpace(nestingBoxRecord.DataUpdateDate)
                    ? hangUpDate ?? DateTime.UtcNow
                    : ParseDate(nestingBoxRecord.DataUpdateDate)
            });
        }
Exemple #9
0
 public SpeciesService(NesteoDbContext dbContext, IMapper mapper) : base(dbContext, mapper)
 {
 }
Exemple #10
0
 public InspectionService(NesteoDbContext dbContext, IMapper mapper, ILateDependency <INestingBoxService> nestingBoxServiceDependency) : base(dbContext,
                                                                                                                                              mapper)
 {
     _nestingBoxServiceDependency = nestingBoxServiceDependency ?? throw new ArgumentNullException(nameof(nestingBoxServiceDependency));
 }
Exemple #11
0
 protected CrudServiceBase(NesteoDbContext dbContext, IMapper mapper)
 {
     DbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
     Mapper    = mapper ?? throw new ArgumentNullException(nameof(mapper));
     Entities  = dbContext.Set <TEntity>();
 }