diff --git a/src/Umbraco.Core/Configuration/InfrastructureSettings/Infrastructure.cs b/src/Umbraco.Core/Configuration/InfrastructureSettings/Infrastructure.cs new file mode 100644 index 0000000000..8a8f4454bc --- /dev/null +++ b/src/Umbraco.Core/Configuration/InfrastructureSettings/Infrastructure.cs @@ -0,0 +1,190 @@ +using System.Configuration; + +namespace Umbraco.Core.Configuration.InfrastructureSettings +{ + public class Infrastructure : ConfigurationSection + { + private const string InfrastructureSectionName = "umbraco/infrastructure"; + + public static Infrastructure Instance + { + get { return (Infrastructure) ConfigurationManager.GetSection(InfrastructureSectionName); } + } + + #region RepositoriesSection Property + + internal const string RepositoriesPropertyName = "repositories"; + + [ConfigurationProperty(RepositoriesPropertyName, IsRequired = true, IsKey = false, IsDefaultCollection = false)] + public Repositories Repositories + { + get { return ((Repositories)base[RepositoriesPropertyName]); } + set { base[RepositoriesPropertyName] = value; } + } + + #endregion + + #region PublishingStrategy Property + + internal const string PublishingStrategyPropertyName = "publishingStrategy"; + + [ConfigurationProperty(PublishingStrategyPropertyName, IsRequired = true, IsKey = false, IsDefaultCollection = false)] + public PublishingProvider PublishingStrategy + { + get { return ((PublishingProvider)base[PublishingStrategyPropertyName]); } + set { base[PublishingStrategyPropertyName] = value; } + } + + #endregion + } + + public class Repositories : ConfigurationElement + { + [ConfigurationProperty("", IsDefaultCollection = true, IsRequired = true)] + public RepositoryElementCollection Repository + { + get { return ((RepositoryElementCollection)(base[""])); } + } + } + + [ConfigurationCollection(typeof(Repository), CollectionType = ConfigurationElementCollectionType.BasicMapAlternate, AddItemName = RepositoryPropertyName)] + public class RepositoryElementCollection : ConfigurationElementCollection + { + internal const string RepositoryPropertyName = "repository"; + + public override ConfigurationElementCollectionType CollectionType + { + get + { + return ConfigurationElementCollectionType.BasicMapAlternate; + } + } + + protected override string ElementName + { + get + { + return RepositoryPropertyName; + } + } + + protected override bool IsElementName(string elementName) + { + return elementName == RepositoryPropertyName; + } + + protected override object GetElementKey(ConfigurationElement element) + { + return ((Repository)element).InterfaceShortTypeName; + } + + protected override ConfigurationElement CreateNewElement() + { + return new Repository(); + } + + #region Indexer + + public Repository this[int index] + { + get { return (Repository)base.BaseGet(index); } + } + + public Repository this[string interfaceShortTypeName] + { + get { return (Repository)base.BaseGet(interfaceShortTypeName); } + } + + #endregion + + #region Add + + public void Add(Repository repository) + { + BaseAdd(repository); + } + + #endregion + + #region Remove + + public void Remove(Repository repository) + { + BaseRemove(repository); + } + + #endregion + + #region GetItem + + public Repository GetItemAt(int index) + { + return (Repository)BaseGet(index); + } + + public Repository GetItemByKey(string interfaceShortTypeName) + { + return (Repository)BaseGet(interfaceShortTypeName); + } + + #endregion + + public bool ContainsKey(string interfaceShortName) + { + bool result = false; + object[] keys = this.BaseGetAllKeys(); + foreach (object key in keys) + { + if ((string)key == interfaceShortName) + { + result = true; + break; + + } + } + return result; + } + } + + public class Repository : ConfigurationElement + { + internal const string InterfaceShortTypeNamePropertyName = "interfaceShortTypeName"; + + [ConfigurationPropertyAttribute(InterfaceShortTypeNamePropertyName, IsRequired = true, IsKey = true, IsDefaultCollection = false)] + public string InterfaceShortTypeName + { + get { return (string) base[InterfaceShortTypeNamePropertyName]; } + set { base[InterfaceShortTypeNamePropertyName] = value; } + } + + internal const string RepositoryFullTypeNamePropertyName = "repositoryFullTypeName"; + + [ConfigurationPropertyAttribute(RepositoryFullTypeNamePropertyName, IsRequired = true, IsKey = false, IsDefaultCollection = false)] + public string RepositoryFullTypeName + { + get { return (string)base[RepositoryFullTypeNamePropertyName]; } + set { base[RepositoryFullTypeNamePropertyName] = value; } + } + + internal const string CacheProviderFullTypeNamePropertyName = "cacheProviderFullTypeName"; + + [ConfigurationPropertyAttribute(CacheProviderFullTypeNamePropertyName, IsRequired = true, IsKey = false, IsDefaultCollection = false)] + public string CacheProviderFullTypeName + { + get { return (string)base[CacheProviderFullTypeNamePropertyName]; } + set { base[CacheProviderFullTypeNamePropertyName] = value; } + } + } + + public class PublishingProvider : ConfigurationElement + { + internal const string TypePropertyName = "type"; + + [ConfigurationPropertyAttribute(TypePropertyName, IsRequired = true, IsKey = false, IsDefaultCollection = false)] + public string Type + { + get { return (string)base[TypePropertyName]; } + set { base[TypePropertyName] = value; } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/DatabaseFactory.cs b/src/Umbraco.Core/Persistence/DatabaseFactory.cs new file mode 100644 index 0000000000..6ce5bd6ac4 --- /dev/null +++ b/src/Umbraco.Core/Persistence/DatabaseFactory.cs @@ -0,0 +1,34 @@ +using System; +using System.Threading; +using Umbraco.Core.Configuration; + +namespace Umbraco.Core.Persistence +{ + /// + /// Provides access to the PetaPoco database as Singleton, so the database is created once in app lifecycle. + /// This is necessary for transactions to work properly + /// + public sealed class DatabaseFactory + { + #region Singleton + + private static readonly Database _database = new Database(GlobalSettings.DbDsn); + private static readonly Lazy lazy = new Lazy(() => new DatabaseFactory()); + + public static DatabaseFactory Current { get { return lazy.Value; } } + + private DatabaseFactory() + { + } + + #endregion + + /// + /// Returns an instance of the PetaPoco database + /// + public Database Database + { + get { return _database; } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Mappers/ModelDtoMapper.cs b/src/Umbraco.Core/Persistence/Mappers/ModelDtoMapper.cs new file mode 100644 index 0000000000..6f43b8e304 --- /dev/null +++ b/src/Umbraco.Core/Persistence/Mappers/ModelDtoMapper.cs @@ -0,0 +1,86 @@ +using System; +using System.Reflection; +using Umbraco.Core.Models; + +namespace Umbraco.Core.Persistence.Mappers +{ + internal class ModelDtoMapper : IMapper + { + public void GetTableInfo(Type t, TableInfo ti) + { } + + public bool MapPropertyToColumn(PropertyInfo pi, ref string columnName, ref bool resultColumn) + { + if (pi.DeclaringType == typeof(Content) || pi.DeclaringType == typeof(IContent)) + { + switch (pi.Name) + { + case "Trashed": + columnName = "[umbracoNode].[trashed]"; + return true; + case "ParentId": + columnName = "[umbracoNode].[parentID]"; + return true; + case "UserId": + columnName = "[umbracoNode].[nodeUser]"; + return true; + case "Level": + columnName = "[umbracoNode].[level]"; + return true; + case "Path": + columnName = "[umbracoNode].[path]"; + return true; + case "SortOrder": + columnName = "[umbracoNode].[sortOrder]"; + return true; + case "NodeId": + columnName = "[umbracoNode].[id]"; + return true; + case "Published": + columnName = "[cmsDocument].[published]"; + return true; + case "Key": + columnName = "[umbracoNode].[uniqueID]"; + return true; + case "CreateDate": + columnName = "[umbracoNode].[createDate]"; + return true; + case "Name": + columnName = "[umbracoNode].[text]"; + return true; + } + } + + if (pi.DeclaringType == typeof(ContentType) || pi.DeclaringType == typeof(IContentType)) + { + switch (pi.Name) + { + case "Alias": + columnName = "[cmsContentType].[alias]"; + return true; + case "Icon": + columnName = "[cmsContentType].[icon]"; + return true; + case "Thumbnail": + columnName = "[cmsContentType].[thumbnail]"; + return true; + case "Description": + columnName = "[cmsContentType].[description]"; + return true; + } + } + + return true; + } + + public Func GetFromDbConverter(PropertyInfo pi, Type sourceType) + { + return null; + } + + public Func GetToDbConverter(Type sourceType) + { + return null; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Querying/ExpressionHelper.cs b/src/Umbraco.Core/Persistence/Querying/ExpressionHelper.cs new file mode 100644 index 0000000000..4a97dc571c --- /dev/null +++ b/src/Umbraco.Core/Persistence/Querying/ExpressionHelper.cs @@ -0,0 +1,572 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Globalization; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using Umbraco.Core.Persistence.Mappers; + +namespace Umbraco.Core.Persistence.Querying +{ + internal class ExpressionHelper + { + private string selectExpression = string.Empty; + private string whereExpression; + private string groupBy = string.Empty; + private string havingExpression; + private string orderBy = string.Empty; + + IList updateFields = new List(); + IList insertFields = new List(); + + private string sep = string.Empty; + private bool useFieldName = false; + private Database.PocoData pd; + + public ExpressionHelper() + { + Database.Mapper = new ModelDtoMapper(); + pd = new Database.PocoData(typeof(T)); + } + + protected internal virtual string Visit(Expression exp) + { + + if (exp == null) return string.Empty; + switch (exp.NodeType) + { + case ExpressionType.Lambda: + return VisitLambda(exp as LambdaExpression); + case ExpressionType.MemberAccess: + return VisitMemberAccess(exp as MemberExpression); + case ExpressionType.Constant: + return VisitConstant(exp as ConstantExpression); + case ExpressionType.Add: + case ExpressionType.AddChecked: + case ExpressionType.Subtract: + case ExpressionType.SubtractChecked: + case ExpressionType.Multiply: + case ExpressionType.MultiplyChecked: + case ExpressionType.Divide: + case ExpressionType.Modulo: + case ExpressionType.And: + case ExpressionType.AndAlso: + case ExpressionType.Or: + case ExpressionType.OrElse: + case ExpressionType.LessThan: + case ExpressionType.LessThanOrEqual: + case ExpressionType.GreaterThan: + case ExpressionType.GreaterThanOrEqual: + case ExpressionType.Equal: + case ExpressionType.NotEqual: + case ExpressionType.Coalesce: + case ExpressionType.ArrayIndex: + case ExpressionType.RightShift: + case ExpressionType.LeftShift: + case ExpressionType.ExclusiveOr: + return "(" + VisitBinary(exp as BinaryExpression) + ")"; + case ExpressionType.Negate: + case ExpressionType.NegateChecked: + case ExpressionType.Not: + case ExpressionType.Convert: + case ExpressionType.ConvertChecked: + case ExpressionType.ArrayLength: + case ExpressionType.Quote: + case ExpressionType.TypeAs: + return VisitUnary(exp as UnaryExpression); + case ExpressionType.Parameter: + return VisitParameter(exp as ParameterExpression); + case ExpressionType.Call: + return VisitMethodCall(exp as MethodCallExpression); + case ExpressionType.New: + return VisitNew(exp as NewExpression); + case ExpressionType.NewArrayInit: + case ExpressionType.NewArrayBounds: + return VisitNewArray(exp as NewArrayExpression); + default: + return exp.ToString(); + } + } + + protected virtual string VisitLambda(LambdaExpression lambda) + { + if (lambda.Body.NodeType == ExpressionType.MemberAccess && sep == " ") + { + MemberExpression m = lambda.Body as MemberExpression; + + if (m.Expression != null) + { + string r = VisitMemberAccess(m); + return string.Format("{0}={1}", r, GetQuotedTrueValue()); + } + + } + return Visit(lambda.Body); + } + + protected virtual string VisitBinary(BinaryExpression b) + { + string left, right; + var operand = BindOperant(b.NodeType); //sep= " " ?? + if (operand == "AND" || operand == "OR") + { + MemberExpression m = b.Left as MemberExpression; + if (m != null && m.Expression != null) + { + string r = VisitMemberAccess(m); + left = string.Format("{0}={1}", r, GetQuotedTrueValue()); + } + else + { + left = Visit(b.Left); + } + m = b.Right as MemberExpression; + if (m != null && m.Expression != null) + { + string r = VisitMemberAccess(m); + right = string.Format("{0}={1}", r, GetQuotedTrueValue()); + } + else + { + right = Visit(b.Right); + } + } + else + { + left = Visit(b.Left); + right = Visit(b.Right); + } + + if (operand == "=" && right == "null") operand = "is"; + else if (operand == "<>" && right == "null") operand = "is not"; + else if (operand == "=" || operand == "<>") + { + if (IsTrueExpression(right)) right = GetQuotedTrueValue(); + else if (IsFalseExpression(right)) right = GetQuotedFalseValue(); + + if (IsTrueExpression(left)) left = GetQuotedTrueValue(); + else if (IsFalseExpression(left)) left = GetQuotedFalseValue(); + + } + + switch (operand) + { + case "MOD": + case "COALESCE": + return string.Format("{0}({1},{2})", operand, left, right); + default: + return left + sep + operand + sep + right; + } + } + + protected virtual string VisitMemberAccess(MemberExpression m) + { + if (m.Expression != null && + m.Expression.NodeType == ExpressionType.Parameter + && m.Expression.Type == typeof(T)) + { + string field = GetFieldName(pd, m.Member.Name); + return field; + } + + if (m.Expression != null && m.Expression.NodeType != ExpressionType.Constant) + { + Database.Mapper = new ModelDtoMapper(); + var def = new Database.PocoData(m.Expression.Type); + string field = GetFieldName(def, m.Member.Name); + return field; + } + + + var member = Expression.Convert(m, typeof(object)); + var lambda = Expression.Lambda>(member); + var getter = lambda.Compile(); + object o = getter(); + return GetQuotedValue(o, o != null ? o.GetType() : null); + + } + + protected virtual string VisitNew(NewExpression nex) + { + // TODO : check ! + var member = Expression.Convert(nex, typeof(object)); + var lambda = Expression.Lambda>(member); + try + { + var getter = lambda.Compile(); + object o = getter(); + return GetQuotedValue(o, o.GetType()); + } + catch (System.InvalidOperationException) + { // FieldName ? + List exprs = VisitExpressionList(nex.Arguments); + var r = new StringBuilder(); + foreach (Object e in exprs) + { + r.AppendFormat("{0}{1}", + r.Length > 0 ? "," : "", + e); + } + return r.ToString(); + } + + } + + protected virtual string VisitParameter(ParameterExpression p) + { + return p.Name; + } + + protected virtual string VisitConstant(ConstantExpression c) + { + if (c.Value == null) + return "null"; + else if (c.Value.GetType() == typeof(bool)) + { + object o = GetQuotedValue(c.Value, c.Value.GetType()); + return string.Format("({0}={1})", GetQuotedTrueValue(), o); + } + else + return GetQuotedValue(c.Value, c.Value.GetType()); + } + + protected virtual string VisitUnary(UnaryExpression u) + { + switch (u.NodeType) + { + case ExpressionType.Not: + string o = Visit(u.Operand); + if (IsFieldName(o)) o = o + "=" + GetQuotedValue(true, typeof(bool)); + return "NOT (" + o + ")"; + default: + return Visit(u.Operand); + } + + } + + protected virtual string VisitMethodCall(MethodCallExpression m) + { + List args = this.VisitExpressionList(m.Arguments); + + Object r; + if (m.Object != null) + r = Visit(m.Object); + else + { + r = args[0]; + args.RemoveAt(0); + } + + switch (m.Method.Name) + { + case "ToUpper": + return string.Format("upper({0})", r); + case "ToLower": + return string.Format("lower({0})", r); + case "StartsWith": + return string.Format("upper({0}) starting with {1} ", r, args[0].ToString().ToUpper()); + case "EndsWith": + return string.Format("upper({0}) like '%{1}'", r, RemoveQuote(args[0].ToString()).ToUpper()); + case "Contains": + return string.Format("upper({0}) like '%{1}%'", r, RemoveQuote(args[0].ToString()).ToUpper()); + case "Substring": + var startIndex = Int32.Parse(args[0].ToString()) + 1; + if (args.Count == 2) + { + var length = Int32.Parse(args[1].ToString()); + return string.Format("substring({0} from {1} for {2})", + r, + startIndex, + length); + } + else + return string.Format("substring({0} from {1})", + r, + startIndex); + case "Round": + case "Floor": + case "Ceiling": + case "Coalesce": + case "Abs": + case "Sum": + return string.Format("{0}({1}{2})", + m.Method.Name, + r, + args.Count == 1 ? string.Format(",{0}", args[0]) : ""); + case "Concat": + var s = new StringBuilder(); + foreach (Object e in args) + { + s.AppendFormat(" || {0}", e); + } + return string.Format("{0}{1}", r, s.ToString()); + + case "In": + + var member = Expression.Convert(m.Arguments[1], typeof(object)); + var lambda = Expression.Lambda>(member); + var getter = lambda.Compile(); + + var inArgs = getter() as object[]; + + var sIn = new StringBuilder(); + foreach (Object e in inArgs) + { + if (e.GetType().ToString() != "System.Collections.Generic.List`1[System.Object]") + { + sIn.AppendFormat("{0}{1}", + sIn.Length > 0 ? "," : "", + GetQuotedValue(e, e.GetType())); + } + else + { + var listArgs = e as IList; + foreach (Object el in listArgs) + { + sIn.AppendFormat("{0}{1}", + sIn.Length > 0 ? "," : "", + GetQuotedValue(el, el.GetType())); + } + } + } + + return string.Format("{0} {1} ({2})", r, m.Method.Name, sIn.ToString()); + case "Desc": + return string.Format("{0} DESC", r); + case "Alias": + case "As": + return string.Format("{0} As {1}", r, + GetQuotedColumnName(RemoveQuoteFromAlias(RemoveQuote(args[0].ToString())))); + case "ToString": + return r.ToString(); + default: + var s2 = new StringBuilder(); + foreach (Object e in args) + { + s2.AppendFormat(",{0}", GetQuotedValue(e, e.GetType())); + } + return string.Format("{0}({1}{2})", m.Method.Name, r, s2.ToString()); + } + } + + protected virtual List VisitExpressionList(ReadOnlyCollection original) + { + var list = new List(); + for (int i = 0, n = original.Count; i < n; i++) + { + if (original[i].NodeType == ExpressionType.NewArrayInit || + original[i].NodeType == ExpressionType.NewArrayBounds) + { + + list.AddRange(VisitNewArrayFromExpressionList(original[i] as NewArrayExpression)); + } + else + list.Add(Visit(original[i])); + + } + return list; + } + + protected virtual string VisitNewArray(NewArrayExpression na) + { + + List exprs = VisitExpressionList(na.Expressions); + var r = new StringBuilder(); + foreach (Object e in exprs) + { + r.Append(r.Length > 0 ? "," + e : e); + } + + return r.ToString(); + } + + protected virtual List VisitNewArrayFromExpressionList(NewArrayExpression na) + { + + List exprs = VisitExpressionList(na.Expressions); + return exprs; + } + + + protected virtual string BindOperant(ExpressionType e) + { + + switch (e) + { + case ExpressionType.Equal: + return "="; + case ExpressionType.NotEqual: + return "<>"; + case ExpressionType.GreaterThan: + return ">"; + case ExpressionType.GreaterThanOrEqual: + return ">="; + case ExpressionType.LessThan: + return "<"; + case ExpressionType.LessThanOrEqual: + return "<="; + case ExpressionType.AndAlso: + return "AND"; + case ExpressionType.OrElse: + return "OR"; + case ExpressionType.Add: + return "+"; + case ExpressionType.Subtract: + return "-"; + case ExpressionType.Multiply: + return "*"; + case ExpressionType.Divide: + return "/"; + case ExpressionType.Modulo: + return "MOD"; + case ExpressionType.Coalesce: + return "COALESCE"; + default: + return e.ToString(); + } + } + + public virtual string GetQuotedTableName(string tableName) + { + return string.Format("\"{0}\"", tableName); + } + + public virtual string GetQuotedColumnName(string columnName) + { + return string.Format("\"{0}\"", columnName); + } + + public virtual string GetQuotedName(string name) + { + return string.Format("\"{0}\"", name); + } + + private string GetQuotedTrueValue() + { + return GetQuotedValue(true, typeof(bool)); + } + + private string GetQuotedFalseValue() + { + return GetQuotedValue(false, typeof(bool)); + } + + public virtual string GetQuotedValue(object value, Type fieldType) + { + if (value == null) return "NULL"; + + if (!fieldType.UnderlyingSystemType.IsValueType && fieldType != typeof(string)) + { + //if (TypeSerializer.CanCreateFromString(fieldType)) + //{ + // return "'" + EscapeParam(TypeSerializer.SerializeToString(value)) + "'"; + //} + + throw new NotSupportedException( + string.Format("Property of type: {0} is not supported", fieldType.FullName)); + } + + if (fieldType == typeof(int)) + return ((int)value).ToString(CultureInfo.InvariantCulture); + + if (fieldType == typeof(float)) + return ((float)value).ToString(CultureInfo.InvariantCulture); + + if (fieldType == typeof(double)) + return ((double)value).ToString(CultureInfo.InvariantCulture); + + if (fieldType == typeof(decimal)) + return ((decimal)value).ToString(CultureInfo.InvariantCulture); + + return ShouldQuoteValue(fieldType) + ? "'" + EscapeParam(value) + "'" + : value.ToString(); + } + + public virtual string EscapeParam(object paramValue) + { + return paramValue.ToString().Replace("'", "''"); + } + + public virtual bool ShouldQuoteValue(Type fieldType) + { + return true; + } + + protected virtual string GetFieldName(Database.PocoData pocoData, string name) + { + var column = pocoData.Columns.FirstOrDefault(x => x.Value.PropertyInfo.Name == name); + return column.Value.ColumnName; + } + + protected virtual string GetFieldName(string name) + { + + if (useFieldName) + { + //FieldDefinition fd = modelDef.FieldDefinitions.FirstOrDefault(x => x.Name == name); + //string fn = fd != default(FieldDefinition) ? fd.FieldName : name; + //return OrmLiteConfig.DialectProvider.GetQuotedColumnName(fn); + return "[" + name + "]"; + } + else + { + return name; + } + } + + protected string RemoveQuote(string exp) + { + + if (exp.StartsWith("'") && exp.EndsWith("'")) + { + exp = exp.Remove(0, 1); + exp = exp.Remove(exp.Length - 1, 1); + } + return exp; + } + + protected string RemoveQuoteFromAlias(string exp) + { + + if ((exp.StartsWith("\"") || exp.StartsWith("`") || exp.StartsWith("'")) + && + (exp.EndsWith("\"") || exp.EndsWith("`") || exp.EndsWith("'"))) + { + exp = exp.Remove(0, 1); + exp = exp.Remove(exp.Length - 1, 1); + } + return exp; + } + + private string GetTrueExpression() + { + object o = GetQuotedTrueValue(); + return string.Format("({0}={1})", o, o); + } + + private string GetFalseExpression() + { + + return string.Format("({0}={1})", + GetQuotedTrueValue(), + GetQuotedFalseValue()); + } + + private bool IsTrueExpression(string exp) + { + return (exp == GetTrueExpression()); + } + + private bool IsFalseExpression(string exp) + { + return (exp == GetFalseExpression()); + } + + protected bool IsFieldName(string quotedExp) + { + return true; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Tests/Configurations/RepositorySettingsTests.cs b/src/Umbraco.Tests/Configurations/RepositorySettingsTests.cs new file mode 100644 index 0000000000..c25bd853b5 --- /dev/null +++ b/src/Umbraco.Tests/Configurations/RepositorySettingsTests.cs @@ -0,0 +1,32 @@ +using System.Configuration; +using NUnit.Framework; +using Umbraco.Core.Configuration.InfrastructureSettings; + +namespace Umbraco.Tests.Configurations +{ + [TestFixture] + public class RepositorySettingsTests + { + [Test] + public void Can_Get_Repository_From_Config() + { + Infrastructure infrastructure = Infrastructure.Instance; + Repositories repositories = infrastructure.Repositories; + Repository repository = repositories.Repository["IContentRepository"]; + + Assert.That(repository, Is.Not.Null); + Assert.AreEqual(repository.InterfaceShortTypeName, "IContentRepository"); + Assert.AreEqual(repository.RepositoryFullTypeName, "Umbraco.Core.Persistence.Repositories.ContentRepository, Umbraco.Core"); + Assert.AreEqual(repository.CacheProviderFullTypeName, "Umbraco.Core.Persistence.Caching.RuntimeCacheProvider, Umbraco.Core"); + } + + [Test] + public void Can_Get_PublishingStrategy_From_Config() + { + Infrastructure infrastructure = Infrastructure.Instance; + PublishingProvider strategy = infrastructure.PublishingStrategy; + + Assert.That(strategy.Type, Is.EqualTo("Umbraco.Web.Publishing.PublishingStrategy, Umbraco.Web")); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Tests/Persistence/DatabaseFactoryTests.cs b/src/Umbraco.Tests/Persistence/DatabaseFactoryTests.cs new file mode 100644 index 0000000000..4a3337f1b2 --- /dev/null +++ b/src/Umbraco.Tests/Persistence/DatabaseFactoryTests.cs @@ -0,0 +1,18 @@ +using NUnit.Framework; +using Umbraco.Core.Persistence; + +namespace Umbraco.Tests.Persistence +{ + [TestFixture] + public class DatabaseFactoryTests + { + [Test] + public void Can_Verify_Single_Database_Instance() + { + var db1 = DatabaseFactory.Current.Database; + var db2 = DatabaseFactory.Current.Database; + + Assert.AreSame(db1, db2); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs index 8400f1afe0..6a942594ae 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs @@ -32,7 +32,7 @@ namespace Umbraco.Tests.Persistence.Repositories }; DataTypesResolver.Current = new DataTypesResolver( - PluginManager.Current.ResolveDataTypes()); + () => PluginManager.Current.ResolveDataTypes()); base.Initialize(); diff --git a/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs index 5e907c53b2..73249bc3a1 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs @@ -32,7 +32,7 @@ namespace Umbraco.Tests.Persistence.Repositories }; DataTypesResolver.Current = new DataTypesResolver( - PluginManager.Current.ResolveDataTypes()); + () => PluginManager.Current.ResolveDataTypes()); base.Initialize();