/// <summary>
 /// Erstellt ein neues Session-Objekt.
 /// </summary>
 /// <param name="id">Anfangswert der Eigenschaft Id.</param>
 /// <param name="clientSessionId">Anfangswert der Eigenschaft ClientSessionId.</param>
 /// <param name="startTime">Anfangswert der Eigenschaft StartTime.</param>
 /// <param name="userId">Anfangswert der Eigenschaft UserId.</param>
 /// <param name="isDebug">Anfangswert der Eigenschaft IsDebug.</param>
 public static Session CreateSession(global::System.Int32 id, global::System.Int64 clientSessionId, global::System.DateTime startTime, global::System.Int32 userId, global::System.Boolean isDebug)
 {
     Session session = new Session();
     session.Id = id;
     session.ClientSessionId = clientSessionId;
     session.StartTime = startTime;
     session.UserId = userId;
     session.IsDebug = isDebug;
     return session;
 }
 /// <summary>
 /// Veraltete Methode zum Hinzufügen eines neuen Objekts zum EntitySet 'Sessions'. Verwenden Sie stattdessen die Methode '.Add' der zugeordneten Eigenschaft 'ObjectSet&lt;T&gt;'.
 /// </summary>
 public void AddToSessions(Session session)
 {
     base.AddObject("Sessions", session);
 }
        // we intentionally don't build the full model in memory first (user -> sessions -> data tables)
        // avoiding concurrency issues (eg type tables) is more important than fewer database writes
        public void ProcessMessage()
        {
            string userGuid = message.UserID.ToString();
            if (String.IsNullOrEmpty(userGuid))
            {
                return;
            }

            PreProcessTypes();

            int userId = repository.FindOrInsertUserByGuid(userGuid);

            /* Session duplicate detection */
            List<long> clientSessionIdList = message.Sessions.Select(s => s.SessionID).ToList();
            if (clientSessionIdList.Count > 0)
            {
                // Match on Id only to execute a T-SQL IN statement
                var potentialDuplicates = (from s in repository.Context.Sessions
                                    where s.UserId == userId && clientSessionIdList.Contains(s.ClientSessionId)
                                    select new { s.ClientSessionId, s.StartTime }).ToList();

                if (potentialDuplicates.Count > 0)
                {
                    // Remove all duplicates that were detected from this message
                    // SQL Server doesn't store times with the same accurracy as .NET; so we only look whether the times were close
                    message.Sessions.RemoveAll(s => potentialDuplicates.Any(d => s.SessionID == d.ClientSessionId && Math.Abs((s.StartTime - d.StartTime).TotalSeconds) < 1));
                }
            }

            List<Session> newSessions = new List<Session>();
            foreach (UsageDataSession msgSession in message.Sessions)
            {
                UsageDataEnvironmentProperty appVersion = msgSession.EnvironmentProperties.FirstOrDefault(ep => ep.Name == "appVersion");
                int appVersionMajor = 0, appVersionMinor = 0, appVersionBuild = 0, appVersionRevision = 0;

                if (null != appVersion && !String.IsNullOrEmpty(appVersion.Value))
                {
                    Version v;
                    if (Version.TryParse(appVersion.Value, out v)) {
                        appVersionMajor = v.Major;
                        appVersionMinor = v.Minor;
                        appVersionBuild = v.Build;
                        appVersionRevision = v.Revision;
                    }
                }

                // Set up the association with the commit; if that's already stored in the database.
                UsageDataEnvironmentProperty commitHash = msgSession.EnvironmentProperties.FirstOrDefault(ep => ep.Name == "commit");
                int? commitId = null;
                if (commitHash != null) {
                    Commit commit = repository.GetCommitByHash(commitHash.Value);
                    if (commit != null) {
                        commitId = commit.Id;
                    }
                }

                Session modelSession = new Session()
                {
                    ClientSessionId = msgSession.SessionID,
                    StartTime = msgSession.StartTime,
                    EndTime = msgSession.EndTime,
                    UserId = userId,
                    AppVersionMajor = appVersionMajor,
                    AppVersionMinor = appVersionMinor,
                    AppVersionBuild = appVersionBuild,
                    AppVersionRevision = appVersionRevision,
                    CommitId = commitId,
                    IsDebug = msgSession.EnvironmentProperties.Any(ep => ep.Name == "debug"),
                    FirstException = msgSession.Exceptions.Min(e => (DateTime?)e.Time), // cast time to nullable to that Min/Max() can return null
                    LastFeatureUse = msgSession.FeatureUses.Max(f => (DateTime?)f.Time) // when there are no exceptions or feature uses
                };

                newSessions.Add(modelSession);
                repository.Context.Sessions.AddObject(modelSession);
            }

            repository.Context.SaveChanges(); // Save #2

            List<EnvironmentDataName> storedEnvNames = ImportCache.GetEnvironmentDataNames(repository);
            List<EnvironmentDataValue> storedEnvValues = ImportCache.GetEnvironmentDataValues(repository);

            var insertEnvProperties = (from s in message.Sessions
                                       from prop in s.EnvironmentProperties
                                       join envName in storedEnvNames on prop.Name equals envName.Name
                                       join envValue in storedEnvValues on prop.Value equals envValue.Name
                                       join storedSession in newSessions on s.SessionID equals storedSession.ClientSessionId
                                       select new EnvironmentData()
                                       {
                                           SessionId = storedSession.Id,
                                           EnvironmentDataNameId = envName.Id,
                                           EnvironmentDataValueId = envValue.Id
                                       });

            foreach (var ede in insertEnvProperties)
                repository.Context.EnvironmentDatas.AddObject(ede);

            List<ActivationMethod> storedActivationMethods = ImportCache.GetActivationMethods(repository);
            List<Feature> storedFeatures = ImportCache.GetFeatures(repository);

            var insertFeatureUse = (from s in message.Sessions
                                    from fu in s.FeatureUses
                                    join f in storedFeatures on fu.FeatureName equals f.Name
                                    join am in storedActivationMethods on fu.ActivationMethod ?? string.Empty equals am.Name
                                    join storedSession in newSessions on s.SessionID equals storedSession.ClientSessionId
                                    select new ICSharpCode.UsageDataCollector.DataAccess.Collector.FeatureUse()
                         {
                             ActivationMethodId = am.Id,
                             FeatureId = f.Id,
                             SessionId = storedSession.Id,
                             UseTime = fu.Time,
                             EndTime = fu.EndTime
                         });

            foreach (var fue in insertFeatureUse)
                repository.Context.FeatureUses.AddObject(fue);

            if (null != denormalisedExceptions)
            {
                List<ExceptionGroup> storedExGroups = ImportCache.GetExceptionGroups(repository);

                var insertExceptions = (from e in denormalisedExceptions
                                        join g in storedExGroups on e.FingerprintHash equals g.TypeFingerprintSha256Hash
                                        join storedSession in newSessions on e.ClientSessionId equals storedSession.ClientSessionId
                                        select new ICSharpCode.UsageDataCollector.DataAccess.Collector.Exception()
                                        {
                                            ExceptionGroupId = g.Id,
                                            SessionId = storedSession.Id,
                                            Stacktrace = e.StackTrace,
                                            ThrownAt = e.Time,
                                            IsFirstInSession = e.IsFirstInSession
                                        });

                foreach (var e in insertExceptions)
                    repository.Context.Exceptions.AddObject(e);
            }

            repository.Context.SaveChanges(); // Save #3
        }