Skip to content

Commit f82c0f3

Browse files
committed
Merge branch '2.5' into feature/mailattach
Conflicts: src/Libraries/SmartStore.Data/SmartStore.Data.csproj
2 parents 5e96c4d + 474c939 commit f82c0f3

70 files changed

Lines changed: 2257 additions & 1329 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
* #727 Web-API: Option to deactivate TimestampOlderThanLastRequest validation
1616
* #731 Web-API: Allow deletion and inserting of product category and manufacturer assignments
1717
* #733 Option to set a display order for homepage products
18+
* #607 HTML capable full description for payment methods displayed in checkout
1819

1920
### Improvements
2021
* (Perf) Implemented static caches for URL aliases and localized properties. Increases app startup and request speed by up to 30%.

src/Libraries/SmartStore.Core/Async/AsyncRunner.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,16 @@ public static class AsyncRunner
1414
{
1515
private static readonly BackgroundWorkHost _host = new BackgroundWorkHost();
1616

17+
/// <summary>
18+
/// Gets the global cancellation token which signals the application shutdown
19+
/// </summary>
20+
public static CancellationToken AppShutdownCancellationToken
21+
{
22+
get { return _host.ShutdownCancellationTokenSource.Token; }
23+
}
1724

1825
/// <summary>
19-
/// Execute's an async Task<T> method which has a void return value synchronously
26+
/// Executes an async Task<T> method which has a void return value synchronously
2027
/// </summary>
2128
/// <param name="func">Task<T> method to execute</param>
2229
public static void RunSync(Func<Task> func)
@@ -46,7 +53,7 @@ public static void RunSync(Func<Task> func)
4653
}
4754

4855
/// <summary>
49-
/// Execute's an async Task<T> method which has a T return type synchronously
56+
/// Executes an async Task<T> method which has a T return type synchronously
5057
/// </summary>
5158
/// <typeparam name="T">Return Type</typeparam>
5259
/// <param name="func">Task<T> method to execute</param>
@@ -291,6 +298,11 @@ public BackgroundWorkHost()
291298
HostingEnvironment.RegisterObject(this);
292299
}
293300

301+
public CancellationTokenSource ShutdownCancellationTokenSource
302+
{
303+
get { return _shutdownCancellationTokenSource; }
304+
}
305+
294306
public void Stop(bool immediate)
295307
{
296308
int num;

src/Libraries/SmartStore.Core/Async/AsyncState.cs

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace SmartStore.Core.Async
1212
public class AsyncState
1313
{
1414
private readonly static AsyncState s_instance = new AsyncState();
15-
private readonly MemoryCache _cache = MemoryCache.Default;
15+
private readonly MemoryCache _cache = new MemoryCache("SmartStore.AsyncState");
1616

1717
private AsyncState()
1818
{
@@ -35,6 +35,22 @@ public T Get<T>(string name = null)
3535
return Get<T>(out cancelTokenSource, name);
3636
}
3737

38+
public IEnumerable<T> GetAll<T>()
39+
{
40+
var keyPrefix = BuildKey<T>(null);
41+
foreach (var kvp in _cache)
42+
{
43+
if (kvp.Key.StartsWith(keyPrefix))
44+
{
45+
var value = kvp.Value as StateInfo;
46+
if (value != null && value.Progress != null)
47+
{
48+
yield return (T)(value.Progress);
49+
}
50+
}
51+
}
52+
}
53+
3854
public CancellationTokenSource GetCancelTokenSource<T>(string name = null)
3955
{
4056
CancellationTokenSource cancelTokenSource;
@@ -46,7 +62,7 @@ private T Get<T>(out CancellationTokenSource cancelTokenSource, string name = nu
4662
{
4763
cancelTokenSource = null;
4864
var key = BuildKey<T>(name);
49-
65+
5066
var value = _cache.Get(key) as StateInfo;
5167

5268
if (value != null)
@@ -60,9 +76,27 @@ private T Get<T>(out CancellationTokenSource cancelTokenSource, string name = nu
6076

6177
public void Set<T>(T state, string name = null, bool neverExpires = false)
6278
{
79+
Guard.ArgumentNotNull(() => state);
6380
this.Set(state, null, name, neverExpires);
6481
}
6582

83+
public void Update<T>(Action<T> update, string name = null)
84+
{
85+
Guard.ArgumentNotNull(() => update);
86+
87+
var key = BuildKey(typeof(T), name);
88+
89+
var value = _cache.Get(key) as StateInfo;
90+
if (value != null)
91+
{
92+
var state = (T)value.Progress;
93+
if (state != null)
94+
{
95+
update(state);
96+
}
97+
}
98+
}
99+
66100
public void SetCancelTokenSource<T>(CancellationTokenSource cancelTokenSource, string name = null)
67101
{
68102
Guard.ArgumentNotNull(() => cancelTokenSource);
@@ -79,7 +113,10 @@ private void Set<T>(T state, CancellationTokenSource cancelTokenSource, string n
79113
if (value != null)
80114
{
81115
// exists already, so update
82-
value.Progress = state;
116+
if (state != null)
117+
{
118+
value.Progress = state;
119+
}
83120
if (cancelTokenSource != null && value.CancellationTokenSource == null)
84121
{
85122
value.CancellationTokenSource = cancelTokenSource;
@@ -88,7 +125,12 @@ private void Set<T>(T state, CancellationTokenSource cancelTokenSource, string n
88125

89126
var policy = new CacheItemPolicy { SlidingExpiration = neverExpires ? TimeSpan.Zero : TimeSpan.FromMinutes(15) };
90127

91-
_cache.Set(key, value ?? new StateInfo { Progress = state, CancellationTokenSource = cancelTokenSource }, policy);
128+
_cache.Set(
129+
key,
130+
value ?? new StateInfo { Progress = state, CancellationTokenSource = cancelTokenSource },
131+
policy);
132+
133+
var xx = _cache.Get(key);
92134
}
93135

94136
public bool Remove<T>(string name = null)

src/Libraries/SmartStore.Core/Data/DbContextScope.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,24 @@ public class DbContextScope : IDisposable
1010
private readonly bool _validateOnSaveEnabled;
1111
private readonly bool _forceNoTracking;
1212
private readonly bool _hooksEnabled;
13+
private readonly bool _autoCommit;
1314
private readonly IDbContext _ctx;
1415

1516
public DbContextScope(IDbContext ctx = null,
1617
bool? autoDetectChanges = null,
1718
bool? proxyCreation = null,
1819
bool? validateOnSave = null,
1920
bool? forceNoTracking = null,
20-
bool? hooksEnabled = null)
21+
bool? hooksEnabled = null,
22+
bool? autoCommit = null)
2123
{
2224
_ctx = ctx ?? EngineContext.Current.Resolve<IDbContext>();
2325
_autoDetectChangesEnabled = _ctx.AutoDetectChangesEnabled;
2426
_proxyCreationEnabled = _ctx.ProxyCreationEnabled;
2527
_validateOnSaveEnabled = _ctx.ValidateOnSaveEnabled;
2628
_forceNoTracking = _ctx.ForceNoTracking;
2729
_hooksEnabled = _ctx.HooksEnabled;
30+
_autoCommit = _ctx.AutoCommitEnabled;
2831

2932
if (autoDetectChanges.HasValue)
3033
_ctx.AutoDetectChangesEnabled = autoDetectChanges.Value;
@@ -40,6 +43,9 @@ public DbContextScope(IDbContext ctx = null,
4043

4144
if (hooksEnabled.HasValue)
4245
_ctx.HooksEnabled = hooksEnabled.Value;
46+
47+
if (autoCommit.HasValue)
48+
_ctx.AutoCommitEnabled = autoCommit.Value;
4349
}
4450

4551
public int Commit()
@@ -54,6 +60,7 @@ public void Dispose()
5460
_ctx.ValidateOnSaveEnabled = _validateOnSaveEnabled;
5561
_ctx.ForceNoTracking = _forceNoTracking;
5662
_ctx.HooksEnabled = _hooksEnabled;
63+
_ctx.AutoCommitEnabled = _autoCommit;
5764
}
5865

5966
}

src/Libraries/SmartStore.Core/Data/IDbContext.cs

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
23
using System.Data;
34
using System.Data.Common;
45
using System.Data.Entity;
@@ -39,7 +40,6 @@ IList<TEntity> ExecuteStoredProcedureList<TEntity>(string commandText, params ob
3940
/// <summary>Executes sql by using SQL-Server Management Objects which supports GO statements.</summary>
4041
int ExecuteSqlThroughSmo(string sql);
4142

42-
// codehint: sm-add (required for UoW implementation)
4343
string Alias { get; }
4444

4545
// increasing performance on bulk operations
@@ -59,6 +59,12 @@ IList<TEntity> ExecuteStoredProcedureList<TEntity>(string commandText, params ob
5959
/// </remarks>
6060
bool ForceNoTracking { get; set; }
6161

62+
/// <summary>
63+
/// Gets or sets a value indicating whether database write operations
64+
/// originating from repositories should be committed immediately.
65+
/// </summary>
66+
bool AutoCommitEnabled { get; set; }
67+
6268
/// <summary>
6369
/// Gets a list of modified properties for the specified entity
6470
/// </summary>
@@ -86,12 +92,6 @@ IList<TEntity> ExecuteStoredProcedureList<TEntity>(string commandText, params ob
8692
/// <param name="entity">The entity instance to detach</param>
8793
void DetachEntity<TEntity>(TEntity entity) where TEntity : BaseEntity, new();
8894

89-
/// <summary>
90-
/// Detaches an entity from the current object context
91-
/// </summary>
92-
/// <param name="entity">The entity instance to detach</param>
93-
void Detach(object entity);
94-
9595
/// <summary>
9696
/// Detaches all entities from the current object context
9797
/// </summary>
@@ -104,15 +104,15 @@ IList<TEntity> ExecuteStoredProcedureList<TEntity>(string commandText, params ob
104104
/// <typeparam name="TEntity">Type of entity</typeparam>
105105
/// <param name="entity">The entity instance</param>
106106
/// <param name="newState">The new state</param>
107-
void ChangeState<TEntity>(TEntity entity, System.Data.Entity.EntityState newState);
107+
void ChangeState<TEntity>(TEntity entity, System.Data.Entity.EntityState newState) where TEntity : BaseEntity, new();
108108

109109
/// <summary>
110-
/// Changes the object state to unchanged
110+
/// Reloads the entity from the database overwriting any property values with values from the database.
111+
/// The entity will be in the Unchanged state after calling this method.
111112
/// </summary>
112113
/// <typeparam name="TEntity">Type of entity</typeparam>
113114
/// <param name="entity">The entity instance</param>
114-
/// <returns>true on success, false on failure</returns>
115-
bool SetToUnchanged<TEntity>(TEntity entity);
115+
void ReloadEntity<TEntity>(TEntity entity) where TEntity : BaseEntity, new();
116116

117117
/// <summary>
118118
/// Begins a transaction on the underlying store connection using the specified isolation level
@@ -127,4 +127,29 @@ IList<TEntity> ExecuteStoredProcedureList<TEntity>(string commandText, params ob
127127
/// <param name="transaction">the external transaction</param>
128128
void UseTransaction(DbTransaction transaction);
129129
}
130+
131+
public static class IDbContextExtensions
132+
{
133+
134+
/// <summary>
135+
/// Changes the object state to unchanged
136+
/// </summary>
137+
/// <typeparam name="TEntity">Type of entity</typeparam>
138+
/// <param name="entity">The entity instance</param>
139+
/// <returns>true on success, false on failure</returns>
140+
public static bool SetToUnchanged<TEntity>(this IDbContext ctx, TEntity entity) where TEntity : BaseEntity, new()
141+
{
142+
try
143+
{
144+
ctx.ChangeState<TEntity>(entity, System.Data.Entity.EntityState.Unchanged);
145+
return true;
146+
}
147+
catch (Exception ex)
148+
{
149+
ex.Dump();
150+
return false;
151+
}
152+
}
153+
154+
}
130155
}

src/Libraries/SmartStore.Core/Data/IRepository.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,10 @@ public partial interface IRepository<T> where T : BaseEntity
119119
/// Gets or sets a value indicating whether database write operations
120120
/// such as insert, delete or update should be committed immediately.
121121
/// </summary>
122-
bool AutoCommitEnabled { get; set; }
122+
/// <remarks>
123+
/// Set this to <c>true</c> or <c>false</c> to supersede the global <c>AutoCommitEnabled</c>
124+
/// on <see cref="IDbContext"/> level for this repository instance only.
125+
/// </remarks>
126+
bool? AutoCommitEnabled { get; set; }
123127
}
124128
}

src/Libraries/SmartStore.Core/Data/RepositoryExtensions.cs

Lines changed: 8 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -63,68 +63,23 @@ public static void Delete<T>(this IRepository<T> rs, object id) where T : BaseEn
6363
/// </remarks>
6464
public static int DeleteAll<T>(this IRepository<T> rs, Expression<Func<T, bool>> predicate = null) where T : BaseEntity
6565
{
66-
var autoCommit = rs.AutoCommitEnabled;
67-
rs.AutoCommitEnabled = false;
68-
6966
var count = 0;
7067

71-
try
68+
using (var scope = new DbContextScope(autoDetectChanges: false, validateOnSave: false, hooksEnabled: false, autoCommit: false))
7269
{
73-
using (var scope = new DbContextScope(autoDetectChanges: false, validateOnSave: false, hooksEnabled: false))
70+
var query = rs.Table;
71+
if (predicate != null)
7472
{
75-
var query = rs.Table;
76-
if (predicate != null)
77-
{
78-
query = query.Where(predicate);
79-
}
80-
81-
var records = query.ToList();
82-
foreach (var chunk in records.Chunk(500))
83-
{
84-
rs.DeleteRange(chunk.ToList());
85-
count += rs.Context.SaveChanges();
86-
}
73+
query = query.Where(predicate);
8774
}
88-
}
89-
catch (Exception ex)
90-
{
91-
throw ex;
92-
}
93-
finally
94-
{
95-
rs.AutoCommitEnabled = autoCommit;
96-
}
9775

98-
return count;
99-
}
100-
101-
private static int DeleteAllInternal<T>(IRepository<T> rs, Expression<Func<T, bool>> predicate) where T : BaseEntity
102-
{
103-
var autoCommit = rs.AutoCommitEnabled;
104-
rs.AutoCommitEnabled = false;
105-
106-
var count = 0;
107-
108-
try
109-
{
110-
using (var scope = new DbContextScope(autoDetectChanges: false, validateOnSave: false, hooksEnabled: false))
76+
var records = query.ToList();
77+
foreach (var chunk in records.Chunk(500))
11178
{
112-
var records = rs.Table.ToList();
113-
foreach (var chunk in records.Chunk(500))
114-
{
115-
rs.DeleteRange(chunk.ToList());
116-
count += rs.Context.SaveChanges();
117-
}
79+
rs.DeleteRange(chunk.ToList());
80+
count += rs.Context.SaveChanges();
11881
}
11982
}
120-
catch (Exception ex)
121-
{
122-
throw ex;
123-
}
124-
finally
125-
{
126-
rs.AutoCommitEnabled = autoCommit;
127-
}
12883

12984
return count;
13085
}

src/Libraries/SmartStore.Core/Domain/Payments/PaymentMethod.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
using System.Runtime.Serialization;
22
using SmartStore.Core.Domain.Common;
3+
using SmartStore.Core.Domain.Localization;
34

45
namespace SmartStore.Core.Domain.Payments
56
{
67
/// <summary>
78
/// Represents a payment method
89
/// </summary>
910
[DataContract]
10-
public partial class PaymentMethod : BaseEntity
11+
public partial class PaymentMethod : BaseEntity, ILocalizedEntity
1112
{
1213
/// <summary>
1314
/// Gets or sets the payment method system name
@@ -88,5 +89,11 @@ public AmountRestrictionContextType AmountRestrictionContext
8889
this.AmountRestrictionContextId = (int)value;
8990
}
9091
}
92+
93+
/// <summary>
94+
/// Gets or sets the full description
95+
/// </summary>
96+
[DataMember]
97+
public string FullDescription { get; set; }
9198
}
9299
}

0 commit comments

Comments
 (0)