@ -1,6 +1,7 @@
#pragma warning disable CS1591
using System ;
using System.Buffers.Text ;
using System.Collections.Generic ;
using System.Globalization ;
using System.IO ;
@ -502,7 +503,7 @@ namespace Emby.Server.Implementations.Data
using ( var saveImagesStatement = base . PrepareStatement ( db , "Update TypedBaseItems set Images=@Images where guid=@Id" ) )
{
saveImagesStatement . TryBind ( "@Id" , item . Id . ToByteArray ( ) ) ;
saveImagesStatement . TryBind ( "@Images" , SerializeImages ( item )) ;
saveImagesStatement . TryBind ( "@Images" , SerializeImages ( item .ImageInfos )) ;
saveImagesStatement . MoveNext ( ) ;
}
@ -897,8 +898,8 @@ namespace Emby.Server.Implementations.Data
saveItemStatement . TryBind ( "@ExternalSeriesId" , item . ExternalSeriesId ) ;
saveItemStatement . TryBind ( "@Tagline" , item . Tagline ) ;
saveItemStatement . TryBind ( "@ProviderIds" , SerializeProviderIds ( item )) ;
saveItemStatement . TryBind ( "@Images" , SerializeImages ( item )) ;
saveItemStatement . TryBind ( "@ProviderIds" , SerializeProviderIds ( item .ProviderIds )) ;
saveItemStatement . TryBind ( "@Images" , SerializeImages ( item .ImageInfos )) ;
if ( item . ProductionLocations . Length > 0 )
{
@ -968,10 +969,10 @@ namespace Emby.Server.Implementations.Data
saveItemStatement . MoveNext ( ) ;
}
private static string SerializeProviderIds ( BaseItem item )
internal static string SerializeProviderIds ( Dictionary < string , string > providerIds )
{
StringBuilder str = new StringBuilder ( ) ;
foreach ( var i in item. P roviderIds)
foreach ( var i in p roviderIds)
{
// Ideally we shouldn't need this IsNullOrWhiteSpace check,
// but we're seeing some cases of bad data slip through
@ -995,35 +996,25 @@ namespace Emby.Server.Implementations.Data
return str . ToString ( ) ;
}
private static void DeserializeProviderIds ( string value , BaseItem item )
internal static void DeserializeProviderIds ( string value , IHasProviderIds item )
{
if ( string . IsNullOrWhiteSpace ( value ) )
{
return ;
}
if ( item . ProviderIds . Count > 0 )
foreach ( var part in value . SpanSplit ( '|' ) )
{
return ;
}
var parts = value . Split ( '|' , StringSplitOptions . RemoveEmptyEntries ) ;
foreach ( var part in parts )
{
var idParts = part . Split ( '=' ) ;
if ( idParts . Length = = 2 )
var providerDelimiterIndex = part . IndexOf ( '=' ) ;
if ( providerDelimiterIndex ! = - 1 & & providerDelimiterIndex = = part . LastIndexOf ( '=' ) )
{
item . SetProviderId ( idParts[ 0 ] , idParts [ 1 ] ) ;
item . SetProviderId ( part . Slice ( 0 , providerDelimiterIndex ) . ToString ( ) , part . Slice ( providerDelimiterIndex + 1 ) . ToString ( ) ) ;
}
}
}
private string SerializeImages ( Base Item i te m)
internal string SerializeImages ( ItemImageInfo [ ] images )
{
var images = item . ImageInfos ;
if ( images . Length = = 0 )
{
return null ;
@ -1045,21 +1036,15 @@ namespace Emby.Server.Implementations.Data
return str . ToString ( ) ;
}
private void DeserializeImages ( string value , BaseItem item )
internal ItemImageInfo [ ] DeserializeImages ( string value )
{
if ( string . IsNullOrWhiteSpace ( value ) )
{
return ;
}
if ( item . ImageInfos . Length > 0 )
{
return ;
return Array . Empty < ItemImageInfo > ( ) ;
}
var parts = value . Split ( '|' , StringSplitOptions . RemoveEmptyEntries ) ;
var list = new List < ItemImageInfo > ( ) ;
foreach ( var part in parts )
foreach ( var part in value . SpanSplit ( '|' ) )
{
var image = ItemImageInfoFromValueString ( part ) ;
@ -1069,15 +1054,14 @@ namespace Emby.Server.Implementations.Data
}
}
item . ImageInfos = list . ToArray ( ) ;
return list . ToArray ( ) ;
}
p ublic void AppendItemImageInfo ( StringBuilder bldr , ItemImageInfo image )
p rivate void AppendItemImageInfo ( StringBuilder bldr , ItemImageInfo image )
{
const char Delimiter = '*' ;
var path = image . Path ? ? string . Empty ;
var hash = image . BlurHash ? ? string . Empty ;
bldr . Append ( GetPathToSave ( path ) )
. Append ( Delimiter )
@ -1087,48 +1071,105 @@ namespace Emby.Server.Implementations.Data
. Append ( Delimiter )
. Append ( image . Width )
. Append ( Delimiter )
. Append ( image . Height )
. Append ( Delimiter )
// Replace delimiters with other characters.
// This can be removed when we migrate to a proper DB.
. Append ( hash . Replace ( '*' , '/' ) . Replace ( '|' , '\\' ) ) ;
. Append ( image . Height ) ;
var hash = image . BlurHash ;
if ( ! string . IsNullOrEmpty ( hash ) )
{
bldr . Append ( Delimiter )
// Replace delimiters with other characters.
// This can be removed when we migrate to a proper DB.
. Append ( hash . Replace ( '*' , '/' ) . Replace ( '|' , '\\' ) ) ;
}
}
public ItemImageInfo ItemImageInfoFromValueString ( string value )
internal ItemImageInfo ItemImageInfoFromValueString ( ReadOnlySpan < char > value )
{
var parts = value . Split ( '*' , StringSplitOptions . None ) ;
var nextSegment = value . IndexOf ( '*' ) ;
if ( nextSegment = = - 1 )
{
return null ;
}
if ( parts . Length < 3 )
ReadOnlySpan < char > path = value [ . . nextSegment ] ;
value = value [ ( nextSegment + 1 ) . . ] ;
nextSegment = value . IndexOf ( '*' ) ;
if ( nextSegment = = - 1 )
{
return null ;
}
var image = new ItemImageInfo ( ) ;
ReadOnlySpan < char > dateModified = value [ . . nextSegment ] ;
value = value [ ( nextSegment + 1 ) . . ] ;
nextSegment = value . IndexOf ( '*' ) ;
if ( nextSegment = = - 1 )
{
nextSegment = value . Length ;
}
ReadOnlySpan < char > imageType = value [ . . nextSegment ] ;
image . Path = RestorePath ( parts [ 0 ] ) ;
var image = new ItemImageInfo
{
Path = RestorePath ( path . ToString ( ) )
} ;
if ( long . TryParse ( parts [ 1 ] , NumberStyles . Any , CultureInfo . InvariantCulture , out var ticks ) )
if ( long . TryParse ( dateModified , NumberStyles . Any , CultureInfo . InvariantCulture , out var ticks ) )
{
image . DateModified = new DateTime ( ticks , DateTimeKind . Utc ) ;
}
if ( Enum . TryParse ( parts[ 2 ] , true , out ImageType type ) )
if ( Enum . TryParse ( imageType. ToString ( ) , true , out ImageType type ) )
{
image . Type = type ;
}
if ( parts . Length > = 5 )
// Optional parameters: width*height*blurhash
if ( nextSegment + 1 < value . Length - 1 )
{
if ( int . TryParse ( parts [ 3 ] , NumberStyles . Integer , CultureInfo . InvariantCulture , out var width )
& & int . TryParse ( parts [ 4 ] , NumberStyles . Integer , CultureInfo . InvariantCulture , out var height ) )
value = value [ ( nextSegment + 1 ) . . ] ;
nextSegment = value . IndexOf ( '*' ) ;
if ( nextSegment = = - 1 | | nextSegment = = value . Length )
{
return image ;
}
ReadOnlySpan < char > widthSpan = value [ . . nextSegment ] ;
value = value [ ( nextSegment + 1 ) . . ] ;
nextSegment = value . IndexOf ( '*' ) ;
if ( nextSegment = = - 1 )
{
nextSegment = value . Length ;
}
ReadOnlySpan < char > heightSpan = value [ . . nextSegment ] ;
if ( int . TryParse ( widthSpan , NumberStyles . Integer , CultureInfo . InvariantCulture , out var width )
& & int . TryParse ( heightSpan , NumberStyles . Integer , CultureInfo . InvariantCulture , out var height ) )
{
image . Width = width ;
image . Height = height ;
}
if ( parts . Length > = 6 )
if ( nextSegment < value . Length - 1 )
{
image . BlurHash = parts [ 5 ] . Replace ( '/' , '*' ) . Replace ( '\\' , '|' ) ;
value = value [ ( nextSegment + 1 ) . . ] ;
var length = value . Length ;
Span < char > blurHashSpan = stackalloc char [ length ] ;
for ( int i = 0 ; i < length ; i + + )
{
var c = value [ i ] ;
blurHashSpan [ i ] = c switch
{
'/' = > '*' ,
'\\' = > '|' ,
_ = > c
} ;
}
image . BlurHash = new string ( blurHashSpan ) ;
}
}
@ -1311,7 +1352,14 @@ namespace Emby.Server.Implementations.Data
if ( ! reader . IsDBNull ( index ) )
{
item . ChannelId = new Guid ( reader . GetString ( index ) ) ;
if ( ! Utf8Parser . TryParse ( reader [ index ] . ToBlob ( ) , out Guid value , out _ , standardFormat : 'N' ) )
{
var str = reader . GetString ( index ) ;
Logger . LogWarning ( "{ChannelId} isn't in the expected format" , str ) ;
value = new Guid ( str ) ;
}
item . ChannelId = value ;
}
index + + ;
@ -1790,7 +1838,7 @@ namespace Emby.Server.Implementations.Data
index + + ;
}
if ( ! reader . IsDBNull ( index ) )
if ( item . ProviderIds . Count = = 0 & & ! reader . IsDBNull ( index ) )
{
DeserializeProviderIds ( reader . GetString ( index ) , item ) ;
}
@ -1799,9 +1847,9 @@ namespace Emby.Server.Implementations.Data
if ( query . DtoOptions . EnableImages )
{
if ( ! reader . IsDBNull ( index ) )
if ( item . ImageInfos . Length = = 0 & & ! reader . IsDBNull ( index ) )
{
DeserializeImages( reader . GetString ( index ) , item ) ;
item. ImageInfos = DeserializeImages( reader . GetString ( index ) ) ;
}
index + + ;
@ -2116,30 +2164,7 @@ namespace Emby.Server.Implementations.Data
| | query . IsLiked . HasValue ;
}
private readonly ItemFields [ ] _allFields = Enum . GetNames ( typeof ( ItemFields ) )
. Select ( i = > ( ItemFields ) Enum . Parse ( typeof ( ItemFields ) , i , true ) )
. ToArray ( ) ;
private string [ ] GetColumnNamesFromField ( ItemFields field )
{
switch ( field )
{
case ItemFields . Settings :
return new [ ] { "IsLocked" , "PreferredMetadataCountryCode" , "PreferredMetadataLanguage" , "LockedFields" } ;
case ItemFields . ServiceName :
return new [ ] { "ExternalServiceId" } ;
case ItemFields . SortName :
return new [ ] { "ForcedSortName" } ;
case ItemFields . Taglines :
return new [ ] { "Tagline" } ;
case ItemFields . Tags :
return new [ ] { "Tags" } ;
case ItemFields . IsHD :
return Array . Empty < string > ( ) ;
default :
return new [ ] { field . ToString ( ) } ;
}
}
private readonly ItemFields [ ] _allFields = Enum . GetValues < ItemFields > ( ) ;
private bool HasField ( InternalItemsQuery query , ItemFields name )
{
@ -2329,9 +2354,32 @@ namespace Emby.Server.Implementations.Data
{
if ( ! HasField ( query , field ) )
{
foreach ( var fieldToRemove in GetColumnNamesFromField ( field ) )
switch ( field )
{
list . Remove ( fieldToRemove ) ;
case ItemFields . Settings :
list . Remove ( "IsLocked" ) ;
list . Remove ( "PreferredMetadataCountryCode" ) ;
list . Remove ( "PreferredMetadataLanguage" ) ;
list . Remove ( "LockedFields" ) ;
break ;
case ItemFields . ServiceName :
list . Remove ( "ExternalServiceId" ) ;
break ;
case ItemFields . SortName :
list . Remove ( "ForcedSortName" ) ;
break ;
case ItemFields . Taglines :
list . Remove ( "Tagline" ) ;
break ;
case ItemFields . Tags :
list . Remove ( "Tags" ) ;
break ;
case ItemFields . IsHD :
// do nothing
break ;
default :
list . Remove ( field . ToString ( ) ) ;
break ;
}
}
}
@ -2578,9 +2626,9 @@ namespace Emby.Server.Implementations.Data
}
var commandText = "select "
+ string . Join ( ',' , GetFinalColumnsToSelect ( query , new [ ] { "count(distinct PresentationUniqueKey)" } ) )
+ GetFromText ( )
+ GetJoinUserDataText ( query ) ;
+ string . Join ( ',' , GetFinalColumnsToSelect ( query , new [ ] { "count(distinct PresentationUniqueKey)" } ) )
+ GetFromText ( )
+ GetJoinUserDataText ( query ) ;
var whereClauses = GetWhereClauses ( query , null ) ;
if ( whereClauses . Count ! = 0 )
@ -2721,87 +2769,22 @@ namespace Emby.Server.Implementations.Data
private string FixUnicodeChars ( string buffer )
{
if ( buffer . IndexOf ( ' \ u2013 ' , StringComparison . Ordinal ) > - 1 )
{
buffer = buffer . Replace ( ' \ u2013 ' , '-' ) ; // en dash
}
if ( buffer . IndexOf ( ' \ u2014 ' , StringComparison . Ordinal ) > - 1 )
{
buffer = buffer . Replace ( ' \ u2014 ' , '-' ) ; // em dash
}
if ( buffer . IndexOf ( ' \ u2015 ' , StringComparison . Ordinal ) > - 1 )
{
buffer = buffer . Replace ( ' \ u2015 ' , '-' ) ; // horizontal bar
}
if ( buffer . IndexOf ( ' \ u2017 ' , StringComparison . Ordinal ) > - 1 )
{
buffer = buffer . Replace ( ' \ u2017 ' , '_' ) ; // double low line
}
if ( buffer . IndexOf ( ' \ u2018 ' , StringComparison . Ordinal ) > - 1 )
{
buffer = buffer . Replace ( ' \ u2018 ' , '\'' ) ; // left single quotation mark
}
if ( buffer . IndexOf ( ' \ u2019 ' , StringComparison . Ordinal ) > - 1 )
{
buffer = buffer . Replace ( ' \ u2019 ' , '\'' ) ; // right single quotation mark
}
if ( buffer . IndexOf ( ' \ u201a ' , StringComparison . Ordinal ) > - 1 )
{
buffer = buffer . Replace ( ' \ u201a ' , ',' ) ; // single low-9 quotation mark
}
if ( buffer . IndexOf ( ' \ u201b ' , StringComparison . Ordinal ) > - 1 )
{
buffer = buffer . Replace ( ' \ u201b ' , '\'' ) ; // single high-reversed-9 quotation mark
}
if ( buffer . IndexOf ( ' \ u201c ' , StringComparison . Ordinal ) > - 1 )
{
buffer = buffer . Replace ( ' \ u201c ' , '\"' ) ; // left double quotation mark
}
if ( buffer . IndexOf ( ' \ u201d ' , StringComparison . Ordinal ) > - 1 )
{
buffer = buffer . Replace ( ' \ u201d ' , '\"' ) ; // right double quotation mark
}
if ( buffer . IndexOf ( ' \ u201e ' , StringComparison . Ordinal ) > - 1 )
{
buffer = buffer . Replace ( ' \ u201e ' , '\"' ) ; // double low-9 quotation mark
}
if ( buffer . IndexOf ( ' \ u2026 ' , StringComparison . Ordinal ) > - 1 )
{
buffer = buffer . Replace ( "\u2026" , "..." , StringComparison . Ordinal ) ; // horizontal ellipsis
}
if ( buffer . IndexOf ( ' \ u2032 ' , StringComparison . Ordinal ) > - 1 )
{
buffer = buffer . Replace ( ' \ u2032 ' , '\'' ) ; // prime
}
if ( buffer . IndexOf ( ' \ u2033 ' , StringComparison . Ordinal ) > - 1 )
{
buffer = buffer . Replace ( ' \ u2033 ' , '\"' ) ; // double prime
}
if ( buffer . IndexOf ( ' \ u0060 ' , StringComparison . Ordinal ) > - 1 )
{
buffer = buffer . Replace ( ' \ u0060 ' , '\'' ) ; // grave accent
}
if ( buffer . IndexOf ( ' \ u00B4 ' , StringComparison . Ordinal ) > - 1 )
{
buffer = buffer . Replace ( ' \ u00B4 ' , '\'' ) ; // acute accent
}
return buffer ;
buffer = buffer . Replace ( ' \ u2013 ' , '-' ) ; // en dash
buffer = buffer . Replace ( ' \ u2014 ' , '-' ) ; // em dash
buffer = buffer . Replace ( ' \ u2015 ' , '-' ) ; // horizontal bar
buffer = buffer . Replace ( ' \ u2017 ' , '_' ) ; // double low line
buffer = buffer . Replace ( ' \ u2018 ' , '\'' ) ; // left single quotation mark
buffer = buffer . Replace ( ' \ u2019 ' , '\'' ) ; // right single quotation mark
buffer = buffer . Replace ( ' \ u201a ' , ',' ) ; // single low-9 quotation mark
buffer = buffer . Replace ( ' \ u201b ' , '\'' ) ; // single high-reversed-9 quotation mark
buffer = buffer . Replace ( ' \ u201c ' , '\"' ) ; // left double quotation mark
buffer = buffer . Replace ( ' \ u201d ' , '\"' ) ; // right double quotation mark
buffer = buffer . Replace ( ' \ u201e ' , '\"' ) ; // double low-9 quotation mark
buffer = buffer . Replace ( "\u2026" , "..." , StringComparison . Ordinal ) ; // horizontal ellipsis
buffer = buffer . Replace ( ' \ u2032 ' , '\'' ) ; // prime
buffer = buffer . Replace ( ' \ u2033 ' , '\"' ) ; // double prime
buffer = buffer . Replace ( ' \ u0060 ' , '\'' ) ; // grave accent
return buffer . Replace ( ' \ u00B4 ' , '\'' ) ; // acute accent
}
private void AddItem ( List < BaseItem > items , BaseItem newItem )
@ -3584,11 +3567,11 @@ namespace Emby.Server.Implementations.Data
statement ? . TryBind ( "@IsFolder" , query . IsFolder ) ;
}
var includeTypes = query . IncludeItemTypes . Select Many ( MapIncludeItemTypes ) . ToArray ( ) ;
var includeTypes = query . IncludeItemTypes . Select ( MapIncludeItemTypes ) . Where ( x = > x ! = null ) . ToArray ( ) ;
// Only specify excluded types if no included types are specified
if ( includeTypes . Length = = 0 )
{
var excludeTypes = query . ExcludeItemTypes . Select Many ( MapIncludeItemTypes ) . ToArray ( ) ;
var excludeTypes = query . ExcludeItemTypes . Select ( MapIncludeItemTypes ) . Where ( x = > x ! = null ) . ToArray ( ) ;
if ( excludeTypes . Length = = 1 )
{
whereClauses . Add ( "type<>@type" ) ;
@ -4532,7 +4515,7 @@ namespace Emby.Server.Implementations.Data
whereClauses . Add ( GetProviderIdClause ( query . HasTvdbId . Value , "tvdb" ) ) ;
}
var includedItemByNameTypes = GetItemByNameTypesInQuery ( query ) .SelectMany ( MapIncludeItemTypes ) . ToList ( ) ;
var includedItemByNameTypes = GetItemByNameTypesInQuery ( query ) ;
var enableItemsByName = ( query . IncludeItemsByName ? ? false ) & & includedItemByNameTypes . Count > 0 ;
var queryTopParentIds = query . TopParentIds ;
@ -4790,27 +4773,27 @@ namespace Emby.Server.Implementations.Data
if ( IsTypeInQuery ( nameof ( Person ) , query ) )
{
list . Add ( nameof ( Person ) ) ;
list . Add ( typeof ( Person ) . FullName ) ;
}
if ( IsTypeInQuery ( nameof ( Genre ) , query ) )
{
list . Add ( nameof ( Genre ) ) ;
list . Add ( typeof ( Genre ) . FullName ) ;
}
if ( IsTypeInQuery ( nameof ( MusicGenre ) , query ) )
{
list . Add ( nameof ( MusicGenre ) ) ;
list . Add ( typeof ( MusicGenre ) . FullName ) ;
}
if ( IsTypeInQuery ( nameof ( MusicArtist ) , query ) )
{
list . Add ( nameof ( MusicArtist ) ) ;
list . Add ( typeof ( MusicArtist ) . FullName ) ;
}
if ( IsTypeInQuery ( nameof ( Studio ) , query ) )
{
list . Add ( nameof ( Studio ) ) ;
list . Add ( typeof ( Studio ) . FullName ) ;
}
return list ;
@ -4915,15 +4898,10 @@ namespace Emby.Server.Implementations.Data
typeof ( AggregateFolder )
} ;
public void UpdateInheritedValues ( CancellationToken cancellationToken )
{
UpdateInheritedTags ( cancellationToken ) ;
}
private void UpdateInheritedTags ( CancellationToken cancellationToken )
public void UpdateInheritedValues ( )
{
string sql = string . Join (
";" ,
';' ,
new string [ ]
{
"delete from itemvalues where type = 6" ,
@ -4946,37 +4924,38 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
}
}
private static Dictionary < string , string [] > GetTypeMapDictionary ( )
private static Dictionary < string , string > GetTypeMapDictionary ( )
{
var dict = new Dictionary < string , string [] >( StringComparer . OrdinalIgnoreCase ) ;
var dict = new Dictionary < string , string >( StringComparer . OrdinalIgnoreCase ) ;
foreach ( var t in _knownTypes )
{
dict [ t . Name ] = new [ ] { t . FullName } ;
dict [ t . Name ] = t . FullName ;
}
dict [ "Program" ] = new[ ] { typeof( LiveTvProgram ) . FullName } ;
dict [ "TvChannel" ] = new[ ] { typeof( LiveTvChannel ) . FullName } ;
dict [ "Program" ] = typeof( LiveTvProgram ) . FullName ;
dict [ "TvChannel" ] = typeof( LiveTvChannel ) . FullName ;
return dict ;
}
// Not crazy about having this all the way down here, but at least it's in one place
private readonly Dictionary < string , string [] > _types = GetTypeMapDictionary ( ) ;
private readonly Dictionary < string , string > _types = GetTypeMapDictionary ( ) ;
private string [ ] MapIncludeItemTypes ( string value )
private string MapIncludeItemTypes ( string value )
{
if ( _types . TryGetValue ( value , out string [ ] result ) )
if ( _types . TryGetValue ( value , out string result ) )
{
return result ;
}
if ( IsValidType ( value ) )
{
return new[ ] { value } ;
return value;
}
return Array . Empty < string > ( ) ;
Logger . LogWarning ( "Unknown item type: {ItemType}" , value ) ;
return null ;
}
public void DeleteItem ( Guid id )
@ -5279,31 +5258,46 @@ AND Type = @InternalPersonType)");
public List < string > GetStudioNames ( )
{
return GetItemValueNames ( new [ ] { 3 } , new List < string > ( ) , new List < string > ( ) ) ;
return GetItemValueNames ( new [ ] { 3 } , Array . Empty < string > ( ) , Array . Empty < string > ( ) ) ;
}
public List < string > GetAllArtistNames ( )
{
return GetItemValueNames ( new [ ] { 0 , 1 } , new List < string > ( ) , new List < string > ( ) ) ;
return GetItemValueNames ( new [ ] { 0 , 1 } , Array . Empty < string > ( ) , Array . Empty < string > ( ) ) ;
}
public List < string > GetMusicGenreNames ( )
{
return GetItemValueNames ( new [ ] { 2 } , new List < string > { "Audio" , "MusicVideo" , "MusicAlbum" , "MusicArtist" } , new List < string > ( ) ) ;
return GetItemValueNames (
new [ ] { 2 } ,
new string [ ]
{
typeof ( Audio ) . FullName ,
typeof ( MusicVideo ) . FullName ,
typeof ( MusicAlbum ) . FullName ,
typeof ( MusicArtist ) . FullName
} ,
Array . Empty < string > ( ) ) ;
}
public List < string > GetGenreNames ( )
{
return GetItemValueNames ( new [ ] { 2 } , new List < string > ( ) , new List < string > { "Audio" , "MusicVideo" , "MusicAlbum" , "MusicArtist" } ) ;
return GetItemValueNames (
new [ ] { 2 } ,
Array . Empty < string > ( ) ,
new string [ ]
{
typeof ( Audio ) . FullName ,
typeof ( MusicVideo ) . FullName ,
typeof ( MusicAlbum ) . FullName ,
typeof ( MusicArtist ) . FullName
} ) ;
}
private List < string > GetItemValueNames ( int [ ] itemValueTypes , List < string > withItemTypes , List < string > excludeItemTypes )
private List < string > GetItemValueNames ( int [ ] itemValueTypes , IReadOnly List< string > withItemTypes , IReadOnly List< string > excludeItemTypes )
{
CheckDisposed ( ) ;
withItemTypes = withItemTypes . SelectMany ( MapIncludeItemTypes ) . ToList ( ) ;
excludeItemTypes = excludeItemTypes . SelectMany ( MapIncludeItemTypes ) . ToList ( ) ;
var now = DateTime . UtcNow ;
var typeClause = itemValueTypes . Length = = 1 ?
@ -5809,7 +5803,10 @@ AND Type = @InternalPersonType)");
var endIndex = Math . Min ( people . Count , startIndex + Limit ) ;
for ( var i = startIndex ; i < endIndex ; i + + )
{
insertText . AppendFormat ( "(@ItemId, @Name{0}, @Role{0}, @PersonType{0}, @SortOrder{0}, @ListOrder{0})," , i . ToString ( CultureInfo . InvariantCulture ) ) ;
insertText . AppendFormat (
CultureInfo . InvariantCulture ,
"(@ItemId, @Name{0}, @Role{0}, @PersonType{0}, @SortOrder{0}, @ListOrder{0})," ,
i . ToString ( CultureInfo . InvariantCulture ) ) ;
}
// Remove last comma
@ -6261,7 +6258,7 @@ AND Type = @InternalPersonType)");
CheckDisposed ( ) ;
if ( id = = Guid . Empty )
{
throw new ArgumentException ( nameof ( id ) ) ;
throw new ArgumentException ( "Guid can't be empty." , nameof ( id ) ) ;
}
if ( attachments = = null )