基于Dynamics CRM字段动态设置Umbraco只读TrueFalse属性并定时更新
实现方案:基于Dynamics CRM动态同步Umbraco文档类型属性并设为只读
完全可以实现你的需求,以下是具体的落地步骤:
一、将目标属性设置为用户只读
后台手动配置方式
在Umbraco后台进入目标文档类型的编辑界面,找到对应的TrueFalse属性:
- 打开属性的「高级设置」面板
- 勾选「锁定值(用户无法编辑)」选项,保存文档类型即可
代码定义文档类型方式
如果是通过代码注册文档类型,在属性配置中添加IsReadOnly = true:
public class EventPageComposer : IComposer { public void Compose(IUmbracoBuilder builder) { builder.ContentTypes() .Define<EventPage>(ctype => ctype .WithAlias("eventPage") .WithName("活动页面") // 配置只读的TrueFalse属性 .AddProperty<bool>(property => property .WithAlias("isActive") .WithName("是否激活") .WithEditor(Constants.PropertyEditors.Aliases.TrueFalse) .IsReadOnly(true) ) // 配置关联CRM Event的ID属性 .AddProperty<int>(property => property .WithAlias("crmEventId") .WithName("CRM活动ID") ) ); } } public class EventPage : PublishedContentModel { public EventPage(IPublishedContent content) : base(content) { } public bool IsActive => this.Value<bool>("isActive"); public int CrmEventId => this.Value<int>("crmEventId"); }
二、实现5分钟间隔的动态同步逻辑
利用.NET的IHostedService结合Umbraco的内容服务,实现定时同步任务:
1. 编写定时同步服务
public class CrmUmbracoSyncService : IHostedService, IDisposable { private readonly IContentService _contentService; private readonly YourCrmDbContext _crmDbContext; private Timer _syncTimer; private readonly TimeSpan _syncInterval = TimeSpan.FromMinutes(5); public CrmUmbracoSyncService(IContentService contentService, YourCrmDbContext crmDbContext) { _contentService = contentService; _crmDbContext = crmDbContext; } public Task StartAsync(CancellationToken cancellationToken) { // 立即执行一次,之后每5分钟执行 _syncTimer = new Timer(SyncData, null, TimeSpan.Zero, _syncInterval); return Task.CompletedTask; } private void SyncData(object state) { try { // 获取所有使用目标文档类型的页面(别名替换为你的文档类型别名) var targetPages = _contentService.GetPagedOfType("eventPage", 0, int.MaxValue, out _).ToList(); foreach (var page in targetPages) { // 读取页面关联的CRM Event ID(属性别名替换为你的实际别名) if (!page.HasProperty("crmEventId")) continue; var crmEventId = page.GetValue<int>("crmEventId"); if (crmEventId == 0) continue; // 从CRM视图查询对应数据(替换为你的视图名和字段名) var crmEvent = _crmDbContext.EventStatusView.FirstOrDefault(e => e.EventId == crmEventId); if (crmEvent == null) continue; // 根据两个数字字段计算布尔值(替换为你的实际判断逻辑) bool targetBoolValue = crmEvent.NumberField1 > 0 && crmEvent.NumberField2 > 0; // 仅当值变化时更新,避免不必要的操作 if (page.GetValue<bool>("isActive") != targetBoolValue) { page.SetValue("isActive", targetBoolValue); // 保存并发布页面,使变更生效 _contentService.SaveAndPublish(page, raiseEvents: false); } } } catch (Exception ex) { // 添加日志记录,便于排查问题 // _logger.LogError(ex, "CRM与Umbraco同步任务执行失败"); } } public Task StopAsync(CancellationToken cancellationToken) { _syncTimer?.Change(Timeout.Infinite, 0); return Task.CompletedTask; } public void Dispose() { _syncTimer?.Dispose(); } }
2. 注册服务
在项目的Program.cs中添加服务注册:
builder.Services.AddHostedService<CrmUmbracoSyncService>();
三、性能优化建议
- 给CRM视图的
EventId字段添加索引,提升查询速度 - 若页面数量较多,可将同步任务拆分为批次处理,避免占用过多资源
- 可结合CRM的变更追踪机制,仅同步最近5分钟内有变化的Event对应的页面,减少不必要的数据库查询
内容的提问来源于stack exchange,提问作者Leth
相关产品推荐
相关产品推荐

