aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs')
-rw-r--r--MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs693
1 files changed, 676 insertions, 17 deletions
diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
index c5a9db87b..852fbd76c 100644
--- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
+++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
@@ -1,14 +1,19 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Serialization;
using System;
using System.Collections.Generic;
using System.Data;
+using System.Globalization;
using System.IO;
using System.Linq;
+using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
@@ -62,6 +67,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
private IDbCommand _saveChildrenCommand;
private IDbCommand _deleteItemCommand;
+ private IDbCommand _deletePeopleCommand;
+ private IDbCommand _savePersonCommand;
/// <summary>
/// Initializes a new instance of the <see cref="SqliteItemRepository"/> class.
/// </summary>
@@ -118,6 +125,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
"create table if not exists ChildrenIds (ParentId GUID, ItemId GUID, PRIMARY KEY (ParentId, ItemId))",
"create index if not exists idx_ChildrenIds on ChildrenIds(ParentId,ItemId)",
+ "create table if not exists People (ItemId GUID, Name TEXT NOT NULL, Role TEXT, PersonType TEXT, SortOrder int, ListOrder int)",
+
//pragmas
"pragma temp_store = memory",
@@ -126,6 +135,27 @@ namespace MediaBrowser.Server.Implementations.Persistence
_connection.RunQueries(queries, _logger);
+ _connection.AddColumn(_logger, "TypedBaseItems", "Path", "Text");
+ _connection.AddColumn(_logger, "TypedBaseItems", "StartDate", "DATETIME");
+ _connection.AddColumn(_logger, "TypedBaseItems", "EndDate", "DATETIME");
+ _connection.AddColumn(_logger, "TypedBaseItems", "ChannelId", "Text");
+ _connection.AddColumn(_logger, "TypedBaseItems", "IsMovie", "BIT");
+ _connection.AddColumn(_logger, "TypedBaseItems", "IsSports", "BIT");
+ _connection.AddColumn(_logger, "TypedBaseItems", "IsKids", "BIT");
+ _connection.AddColumn(_logger, "TypedBaseItems", "CommunityRating", "Float");
+ _connection.AddColumn(_logger, "TypedBaseItems", "CustomRating", "Text");
+ _connection.AddColumn(_logger, "TypedBaseItems", "IndexNumber", "INT");
+ _connection.AddColumn(_logger, "TypedBaseItems", "IsLocked", "BIT");
+ _connection.AddColumn(_logger, "TypedBaseItems", "Name", "Text");
+ _connection.AddColumn(_logger, "TypedBaseItems", "OfficialRating", "Text");
+
+ _connection.AddColumn(_logger, "TypedBaseItems", "MediaType", "Text");
+ _connection.AddColumn(_logger, "TypedBaseItems", "Overview", "Text");
+ _connection.AddColumn(_logger, "TypedBaseItems", "ParentIndexNumber", "INT");
+ _connection.AddColumn(_logger, "TypedBaseItems", "PremiereDate", "DATETIME");
+ _connection.AddColumn(_logger, "TypedBaseItems", "ProductionYear", "INT");
+ _connection.AddColumn(_logger, "TypedBaseItems", "ParentId", "GUID");
+
PrepareStatements();
_mediaStreamsRepository.Initialize();
@@ -142,11 +172,37 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// </summary>
private void PrepareStatements()
{
+ var saveColumns = new List<string>
+ {
+ "guid",
+ "type",
+ "data",
+ "Path",
+ "StartDate",
+ "EndDate",
+ "ChannelId",
+ "IsKids",
+ "IsMovie",
+ "IsSports",
+ "CommunityRating",
+ "CustomRating",
+ "IndexNumber",
+ "IsLocked",
+ "Name",
+ "OfficialRating",
+ "MediaType",
+ "Overview",
+ "ParentIndexNumber",
+ "PremiereDate",
+ "ProductionYear",
+ "ParentId"
+ };
_saveItemCommand = _connection.CreateCommand();
- _saveItemCommand.CommandText = "replace into TypedBaseItems (guid, type, data) values (@1, @2, @3)";
- _saveItemCommand.Parameters.Add(_saveItemCommand, "@1");
- _saveItemCommand.Parameters.Add(_saveItemCommand, "@2");
- _saveItemCommand.Parameters.Add(_saveItemCommand, "@3");
+ _saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values (@1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @11, @12, @13, @14, @15, @16, @17, @18, @19, @20, @21, @22)";
+ for (var i = 1; i <= saveColumns.Count; i++)
+ {
+ _saveItemCommand.Parameters.Add(_saveItemCommand, "@" + i.ToString(CultureInfo.InvariantCulture));
+ }
_deleteChildrenCommand = _connection.CreateCommand();
_deleteChildrenCommand.CommandText = "delete from ChildrenIds where ParentId=@ParentId";
@@ -155,11 +211,24 @@ namespace MediaBrowser.Server.Implementations.Persistence
_deleteItemCommand = _connection.CreateCommand();
_deleteItemCommand.CommandText = "delete from TypedBaseItems where guid=@Id";
_deleteItemCommand.Parameters.Add(_deleteItemCommand, "@Id");
-
+
_saveChildrenCommand = _connection.CreateCommand();
_saveChildrenCommand.CommandText = "replace into ChildrenIds (ParentId, ItemId) values (@ParentId, @ItemId)";
_saveChildrenCommand.Parameters.Add(_saveChildrenCommand, "@ParentId");
_saveChildrenCommand.Parameters.Add(_saveChildrenCommand, "@ItemId");
+
+ _deletePeopleCommand = _connection.CreateCommand();
+ _deletePeopleCommand.CommandText = "delete from People where ItemId=@Id";
+ _deletePeopleCommand.Parameters.Add(_deletePeopleCommand, "@Id");
+
+ _savePersonCommand = _connection.CreateCommand();
+ _savePersonCommand.CommandText = "insert into People (ItemId, Name, Role, PersonType, SortOrder, ListOrder) values (@ItemId, @Name, @Role, @PersonType, @SortOrder, @ListOrder)";
+ _savePersonCommand.Parameters.Add(_savePersonCommand, "@ItemId");
+ _savePersonCommand.Parameters.Add(_savePersonCommand, "@Name");
+ _savePersonCommand.Parameters.Add(_savePersonCommand, "@Role");
+ _savePersonCommand.Parameters.Add(_savePersonCommand, "@PersonType");
+ _savePersonCommand.Parameters.Add(_savePersonCommand, "@SortOrder");
+ _savePersonCommand.Parameters.Add(_savePersonCommand, "@ListOrder");
}
/// <summary>
@@ -200,7 +269,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
cancellationToken.ThrowIfCancellationRequested();
CheckDisposed();
-
+
await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false);
IDbTransaction transaction = null;
@@ -213,9 +282,64 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
cancellationToken.ThrowIfCancellationRequested();
- _saveItemCommand.GetParameter(0).Value = item.Id;
- _saveItemCommand.GetParameter(1).Value = item.GetType().FullName;
- _saveItemCommand.GetParameter(2).Value = _jsonSerializer.SerializeToBytes(item);
+ var index = 0;
+
+ _saveItemCommand.GetParameter(index++).Value = item.Id;
+ _saveItemCommand.GetParameter(index++).Value = item.GetType().FullName;
+ _saveItemCommand.GetParameter(index++).Value = _jsonSerializer.SerializeToBytes(item);
+
+ _saveItemCommand.GetParameter(index++).Value = item.Path;
+
+ var hasStartDate = item as IHasStartDate;
+ if (hasStartDate != null)
+ {
+ _saveItemCommand.GetParameter(index++).Value = hasStartDate.StartDate;
+ }
+ else
+ {
+ _saveItemCommand.GetParameter(index++).Value = null;
+ }
+
+ _saveItemCommand.GetParameter(index++).Value = item.EndDate;
+ _saveItemCommand.GetParameter(index++).Value = item.ChannelId;
+
+ var hasProgramAttributes = item as IHasProgramAttributes;
+ if (hasProgramAttributes != null)
+ {
+ _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsKids;
+ _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsMovie;
+ _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsSports;
+ }
+ else
+ {
+ _saveItemCommand.GetParameter(index++).Value = null;
+ _saveItemCommand.GetParameter(index++).Value = null;
+ _saveItemCommand.GetParameter(index++).Value = null;
+ }
+
+ _saveItemCommand.GetParameter(index++).Value = item.CommunityRating;
+ _saveItemCommand.GetParameter(index++).Value = item.CustomRating;
+
+ _saveItemCommand.GetParameter(index++).Value = item.IndexNumber;
+ _saveItemCommand.GetParameter(index++).Value = item.IsLocked;
+
+ _saveItemCommand.GetParameter(index++).Value = item.Name;
+ _saveItemCommand.GetParameter(index++).Value = item.OfficialRating;
+
+ _saveItemCommand.GetParameter(index++).Value = item.MediaType;
+ _saveItemCommand.GetParameter(index++).Value = item.Overview;
+ _saveItemCommand.GetParameter(index++).Value = item.ParentIndexNumber;
+ _saveItemCommand.GetParameter(index++).Value = item.PremiereDate;
+ _saveItemCommand.GetParameter(index++).Value = item.ProductionYear;
+
+ if (item.ParentId == Guid.Empty)
+ {
+ _saveItemCommand.GetParameter(index++).Value = null;
+ }
+ else
+ {
+ _saveItemCommand.GetParameter(index++).Value = item.ParentId;
+ }
_saveItemCommand.Transaction = transaction;
@@ -254,7 +378,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
_writeLock.Release();
}
}
-
+
/// <summary>
/// Internal retrieve from items or users table
/// </summary>
@@ -270,7 +394,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
CheckDisposed();
-
+
using (var cmd = _connection.CreateCommand())
{
cmd.CommandText = "select type,data from TypedBaseItems where guid = @guid";
@@ -302,7 +426,15 @@ namespace MediaBrowser.Server.Implementations.Persistence
using (var stream = reader.GetMemoryStream(1))
{
- return _jsonSerializer.DeserializeFromStream(stream, type) as BaseItem;
+ try
+ {
+ return _jsonSerializer.DeserializeFromStream(stream, type) as BaseItem;
+ }
+ catch (SerializationException ex)
+ {
+ _logger.ErrorException("Error deserializing item", ex);
+ return null;
+ }
}
}
@@ -467,7 +599,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
CheckDisposed();
-
+
using (var cmd = _connection.CreateCommand())
{
cmd.CommandText = "select ItemId from ChildrenIds where ParentId = @ParentId";
@@ -492,7 +624,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
CheckDisposed();
-
+
using (var cmd = _connection.CreateCommand())
{
cmd.CommandText = "select type,data from TypedBaseItems where guid in (select ItemId from ChildrenIds where ParentId = @ParentId)";
@@ -544,6 +676,299 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
}
+ public QueryResult<BaseItem> GetItems(InternalItemsQuery query)
+ {
+ if (query == null)
+ {
+ throw new ArgumentNullException("query");
+ }
+
+ CheckDisposed();
+
+ using (var cmd = _connection.CreateCommand())
+ {
+ cmd.CommandText = "select type,data from TypedBaseItems";
+
+ var whereClauses = GetWhereClauses(query, cmd, false);
+
+ var whereTextWithoutPaging = whereClauses.Count == 0 ?
+ string.Empty :
+ " where " + string.Join(" AND ", whereClauses.ToArray());
+
+ whereClauses = GetWhereClauses(query, cmd, true);
+
+ var whereText = whereClauses.Count == 0 ?
+ string.Empty :
+ " where " + string.Join(" AND ", whereClauses.ToArray());
+
+ cmd.CommandText += whereText;
+
+ if (query.Limit.HasValue)
+ {
+ cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(CultureInfo.InvariantCulture);
+ }
+
+ cmd.CommandText += "; select count (guid) from TypedBaseItems" + whereTextWithoutPaging;
+
+ var list = new List<BaseItem>();
+ var count = 0;
+
+ using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
+ {
+ while (reader.Read())
+ {
+ var item = GetItem(reader);
+ if (item != null)
+ {
+ list.Add(item);
+ }
+ }
+
+ if (reader.NextResult() && reader.Read())
+ {
+ count = reader.GetInt32(0);
+ }
+ }
+
+ return new QueryResult<BaseItem>()
+ {
+ Items = list.ToArray(),
+ TotalRecordCount = count
+ };
+ }
+ }
+
+ public List<Guid> GetItemIdsList(InternalItemsQuery query)
+ {
+ if (query == null)
+ {
+ throw new ArgumentNullException("query");
+ }
+
+ CheckDisposed();
+
+ using (var cmd = _connection.CreateCommand())
+ {
+ cmd.CommandText = "select guid from TypedBaseItems";
+
+ var whereClauses = GetWhereClauses(query, cmd, true);
+
+ var whereText = whereClauses.Count == 0 ?
+ string.Empty :
+ " where " + string.Join(" AND ", whereClauses.ToArray());
+
+ cmd.CommandText += whereText;
+
+ if (query.Limit.HasValue)
+ {
+ cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(CultureInfo.InvariantCulture);
+ }
+
+ var list = new List<Guid>();
+
+ _logger.Debug(cmd.CommandText);
+
+ using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
+ {
+ while (reader.Read())
+ {
+ list.Add(reader.GetGuid(0));
+ }
+ }
+
+ return list;
+ }
+ }
+
+ public QueryResult<Guid> GetItemIds(InternalItemsQuery query)
+ {
+ if (query == null)
+ {
+ throw new ArgumentNullException("query");
+ }
+
+ CheckDisposed();
+
+ using (var cmd = _connection.CreateCommand())
+ {
+ cmd.CommandText = "select guid from TypedBaseItems";
+
+ var whereClauses = GetWhereClauses(query, cmd, false);
+
+ var whereTextWithoutPaging = whereClauses.Count == 0 ?
+ string.Empty :
+ " where " + string.Join(" AND ", whereClauses.ToArray());
+
+ whereClauses = GetWhereClauses(query, cmd, true);
+
+ var whereText = whereClauses.Count == 0 ?
+ string.Empty :
+ " where " + string.Join(" AND ", whereClauses.ToArray());
+
+ cmd.CommandText += whereText;
+
+ if (query.Limit.HasValue)
+ {
+ cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(CultureInfo.InvariantCulture);
+ }
+
+ cmd.CommandText += "; select count (guid) from TypedBaseItems" + whereTextWithoutPaging;
+
+ var list = new List<Guid>();
+ var count = 0;
+
+ _logger.Debug(cmd.CommandText);
+
+ using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
+ {
+ while (reader.Read())
+ {
+ list.Add(reader.GetGuid(0));
+ }
+
+ if (reader.NextResult() && reader.Read())
+ {
+ count = reader.GetInt32(0);
+ }
+ }
+
+ return new QueryResult<Guid>()
+ {
+ Items = list.ToArray(),
+ TotalRecordCount = count
+ };
+ }
+ }
+
+ private List<string> GetWhereClauses(InternalItemsQuery query, IDbCommand cmd, bool addPaging)
+ {
+ var whereClauses = new List<string>();
+
+ if (query.IsMovie.HasValue)
+ {
+ whereClauses.Add("IsMovie=@IsMovie");
+ cmd.Parameters.Add(cmd, "@IsMovie", DbType.Boolean).Value = query.IsMovie;
+ }
+ if (query.IsKids.HasValue)
+ {
+ whereClauses.Add("IsKids=@IsKids");
+ cmd.Parameters.Add(cmd, "@IsKids", DbType.Boolean).Value = query.IsKids;
+ }
+ if (query.IsSports.HasValue)
+ {
+ whereClauses.Add("IsSports=@IsSports");
+ cmd.Parameters.Add(cmd, "@IsSports", DbType.Boolean).Value = query.IsSports;
+ }
+
+ var includeTypes = query.IncludeItemTypes.SelectMany(MapIncludeItemTypes).ToArray();
+
+ if (includeTypes.Length == 1)
+ {
+ whereClauses.Add("type=@type");
+ cmd.Parameters.Add(cmd, "@type", DbType.String).Value = includeTypes[0];
+ }
+ if (includeTypes.Length > 1)
+ {
+ var inClause = string.Join(",", includeTypes.Select(i => "'" + i + "'").ToArray());
+ whereClauses.Add(string.Format("type in ({0})", inClause));
+ }
+ if (query.ChannelIds.Length == 1)
+ {
+ whereClauses.Add("ChannelId=@ChannelId");
+ cmd.Parameters.Add(cmd, "@ChannelId", DbType.String).Value = query.ChannelIds[0];
+ }
+ if (query.ChannelIds.Length > 1)
+ {
+ var inClause = string.Join(",", query.ChannelIds.Select(i => "'" + i + "'").ToArray());
+ whereClauses.Add(string.Format("ChannelId in ({0})", inClause));
+ }
+
+ if (query.MinEndDate.HasValue)
+ {
+ whereClauses.Add("EndDate>=@MinEndDate");
+ cmd.Parameters.Add(cmd, "@MinEndDate", DbType.Date).Value = query.MinEndDate.Value;
+ }
+
+ if (query.MaxEndDate.HasValue)
+ {
+ whereClauses.Add("EndDate<=@MaxEndDate");
+ cmd.Parameters.Add(cmd, "@MaxEndDate", DbType.Date).Value = query.MaxEndDate.Value;
+ }
+
+ if (query.MinStartDate.HasValue)
+ {
+ whereClauses.Add("StartDate>=@MinStartDate");
+ cmd.Parameters.Add(cmd, "@MinStartDate", DbType.Date).Value = query.MinStartDate.Value;
+ }
+
+ if (query.MaxStartDate.HasValue)
+ {
+ whereClauses.Add("StartDate<=@MaxStartDate");
+ cmd.Parameters.Add(cmd, "@MaxStartDate", DbType.Date).Value = query.MaxStartDate.Value;
+ }
+
+ if (query.IsAiring.HasValue)
+ {
+ if (query.IsAiring.Value)
+ {
+ whereClauses.Add("StartDate<=@MaxStartDate");
+ cmd.Parameters.Add(cmd, "@MaxStartDate", DbType.Date).Value = DateTime.UtcNow;
+
+ whereClauses.Add("EndDate>=@MinEndDate");
+ cmd.Parameters.Add(cmd, "@MinEndDate", DbType.Date).Value = DateTime.UtcNow;
+ }
+ else
+ {
+ whereClauses.Add("(StartDate>@IsAiringDate OR EndDate < @IsAiringDate)");
+ cmd.Parameters.Add(cmd, "@IsAiringDate", DbType.Date).Value = DateTime.UtcNow;
+ }
+ }
+
+ if (!string.IsNullOrWhiteSpace(query.Person))
+ {
+ whereClauses.Add("Guid in (select ItemId from People where Name=@PersonName)");
+ cmd.Parameters.Add(cmd, "@PersonName", DbType.String).Value = query.Person;
+ }
+
+ if (addPaging)
+ {
+ if (query.StartIndex.HasValue && query.StartIndex.Value > 0)
+ {
+ var pagingWhereText = whereClauses.Count == 0 ?
+ string.Empty :
+ " where " + string.Join(" AND ", whereClauses.ToArray());
+
+ whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM TypedBaseItems {0} ORDER BY DateCreated DESC LIMIT {1})",
+ pagingWhereText,
+ query.StartIndex.Value.ToString(CultureInfo.InvariantCulture)));
+ }
+ }
+
+ return whereClauses;
+ }
+
+ // Not crazy about having this all the way down here, but at least it's in one place
+ readonly Dictionary<string, string[]> _types = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase)
+ {
+ {typeof(LiveTvProgram).Name, new []{typeof(LiveTvProgram).FullName}},
+ {typeof(LiveTvChannel).Name, new []{typeof(LiveTvChannel).FullName}},
+ {typeof(LiveTvVideoRecording).Name, new []{typeof(LiveTvVideoRecording).FullName}},
+ {typeof(LiveTvAudioRecording).Name, new []{typeof(LiveTvAudioRecording).FullName}},
+ {typeof(Series).Name, new []{typeof(Series).FullName}},
+ {"Recording", new []{typeof(LiveTvAudioRecording).FullName, typeof(LiveTvVideoRecording).FullName}}
+ };
+
+ private IEnumerable<string> MapIncludeItemTypes(string value)
+ {
+ string[] result;
+ if (_types.TryGetValue(value, out result))
+ {
+ return result;
+ }
+
+ return new[] { value };
+ }
+
public IEnumerable<Guid> GetItemIdsOfType(Type type)
{
if (type == null)
@@ -577,7 +1002,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
CheckDisposed();
-
+
await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false);
IDbTransaction transaction = null;
@@ -591,11 +1016,16 @@ namespace MediaBrowser.Server.Implementations.Persistence
_deleteChildrenCommand.Transaction = transaction;
_deleteChildrenCommand.ExecuteNonQuery();
+ // Delete people
+ _deletePeopleCommand.GetParameter(0).Value = id;
+ _deletePeopleCommand.Transaction = transaction;
+ _deletePeopleCommand.ExecuteNonQuery();
+
// Delete the item
_deleteItemCommand.GetParameter(0).Value = id;
_deleteItemCommand.Transaction = transaction;
_deleteItemCommand.ExecuteNonQuery();
-
+
transaction.Commit();
}
catch (OperationCanceledException)
@@ -642,7 +1072,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
CheckDisposed();
-
+
await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false);
IDbTransaction transaction = null;
@@ -713,5 +1143,234 @@ namespace MediaBrowser.Server.Implementations.Persistence
CheckDisposed();
return _mediaStreamsRepository.SaveMediaStreams(id, streams, cancellationToken);
}
+
+ public List<string> GetPeopleNames(InternalPeopleQuery query)
+ {
+ if (query == null)
+ {
+ throw new ArgumentNullException("query");
+ }
+
+ CheckDisposed();
+
+ using (var cmd = _connection.CreateCommand())
+ {
+ cmd.CommandText = "select Distinct Name from People";
+
+ var whereClauses = GetPeopleWhereClauses(query, cmd);
+
+ if (whereClauses.Count > 0)
+ {
+ cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray());
+ }
+
+ cmd.CommandText += " order by ListOrder";
+
+ var list = new List<string>();
+
+ using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
+ {
+ while (reader.Read())
+ {
+ list.Add(reader.GetString(0));
+ }
+ }
+
+ return list;
+ }
+ }
+
+ public List<PersonInfo> GetPeople(InternalPeopleQuery query)
+ {
+ if (query == null)
+ {
+ throw new ArgumentNullException("query");
+ }
+
+ CheckDisposed();
+
+ using (var cmd = _connection.CreateCommand())
+ {
+ cmd.CommandText = "select ItemId, Name, Role, PersonType, SortOrder from People";
+
+ var whereClauses = GetPeopleWhereClauses(query, cmd);
+
+ if (whereClauses.Count > 0)
+ {
+ cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray());
+ }
+
+ cmd.CommandText += " order by ListOrder";
+
+ var list = new List<PersonInfo>();
+
+ using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
+ {
+ while (reader.Read())
+ {
+ list.Add(GetPerson(reader));
+ }
+ }
+
+ return list;
+ }
+ }
+
+ private List<string> GetPeopleWhereClauses(InternalPeopleQuery query, IDbCommand cmd)
+ {
+ var whereClauses = new List<string>();
+
+ if (query.ItemId != Guid.Empty)
+ {
+ whereClauses.Add("ItemId=@ItemId");
+ cmd.Parameters.Add(cmd, "@ItemId", DbType.Guid).Value = query.ItemId;
+ }
+ if (query.AppearsInItemId != Guid.Empty)
+ {
+ whereClauses.Add("Name in (Select Name from People where ItemId=@AppearsInItemId)");
+ cmd.Parameters.Add(cmd, "@AppearsInItemId", DbType.Guid).Value = query.AppearsInItemId;
+ }
+ if (query.PersonTypes.Count == 1)
+ {
+ whereClauses.Add("PersonType=@PersonType");
+ cmd.Parameters.Add(cmd, "@PersonType", DbType.String).Value = query.PersonTypes[0];
+ }
+ if (query.PersonTypes.Count > 1)
+ {
+ var val = string.Join(",", query.PersonTypes.Select(i => "'" + i + "'").ToArray());
+
+ whereClauses.Add("PersonType in (" + val + ")");
+ }
+ if (query.ExcludePersonTypes.Count == 1)
+ {
+ whereClauses.Add("PersonType<>@PersonType");
+ cmd.Parameters.Add(cmd, "@PersonType", DbType.String).Value = query.ExcludePersonTypes[0];
+ }
+ if (query.ExcludePersonTypes.Count > 1)
+ {
+ var val = string.Join(",", query.ExcludePersonTypes.Select(i => "'" + i + "'").ToArray());
+
+ whereClauses.Add("PersonType not in (" + val + ")");
+ }
+ if (query.MaxListOrder.HasValue)
+ {
+ whereClauses.Add("ListOrder<=@MaxListOrder");
+ cmd.Parameters.Add(cmd, "@MaxListOrder", DbType.Int32).Value = query.MaxListOrder.Value;
+ }
+ if (!string.IsNullOrWhiteSpace(query.NameContains))
+ {
+ whereClauses.Add("Name like @NameContains");
+ cmd.Parameters.Add(cmd, "@NameContains", DbType.String).Value = "%"+query.NameContains+"%";
+ }
+
+ return whereClauses;
+ }
+
+ public async Task UpdatePeople(Guid itemId, List<PersonInfo> people)
+ {
+ if (itemId == Guid.Empty)
+ {
+ throw new ArgumentNullException("itemId");
+ }
+
+ if (people == null)
+ {
+ throw new ArgumentNullException("people");
+ }
+
+ CheckDisposed();
+
+ var cancellationToken = CancellationToken.None;
+
+ await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false);
+
+ IDbTransaction transaction = null;
+
+ try
+ {
+ transaction = _connection.BeginTransaction();
+
+ // First delete
+ _deletePeopleCommand.GetParameter(0).Value = itemId;
+ _deletePeopleCommand.Transaction = transaction;
+
+ _deletePeopleCommand.ExecuteNonQuery();
+
+ var listIndex = 0;
+
+ foreach (var person in people)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ _savePersonCommand.GetParameter(0).Value = itemId;
+ _savePersonCommand.GetParameter(1).Value = person.Name;
+ _savePersonCommand.GetParameter(2).Value = person.Role;
+ _savePersonCommand.GetParameter(3).Value = person.Type;
+ _savePersonCommand.GetParameter(4).Value = person.SortOrder;
+ _savePersonCommand.GetParameter(5).Value = listIndex;
+
+ _savePersonCommand.Transaction = transaction;
+
+ _savePersonCommand.ExecuteNonQuery();
+ listIndex++;
+ }
+
+ transaction.Commit();
+ }
+ catch (OperationCanceledException)
+ {
+ if (transaction != null)
+ {
+ transaction.Rollback();
+ }
+
+ throw;
+ }
+ catch (Exception e)
+ {
+ _logger.ErrorException("Failed to save people:", e);
+
+ if (transaction != null)
+ {
+ transaction.Rollback();
+ }
+
+ throw;
+ }
+ finally
+ {
+ if (transaction != null)
+ {
+ transaction.Dispose();
+ }
+
+ _writeLock.Release();
+ }
+ }
+
+ private PersonInfo GetPerson(IDataReader reader)
+ {
+ var item = new PersonInfo();
+
+ item.ItemId = reader.GetGuid(0);
+ item.Name = reader.GetString(1);
+
+ if (!reader.IsDBNull(2))
+ {
+ item.Role = reader.GetString(2);
+ }
+
+ if (!reader.IsDBNull(3))
+ {
+ item.Type = reader.GetString(3);
+ }
+
+ if (!reader.IsDBNull(4))
+ {
+ item.SortOrder = reader.GetInt32(4);
+ }
+
+ return item;
+ }
}
} \ No newline at end of file