Вы все еще можете использовать ключевое слово using
в Mule 4 / Dataweave 2.
Локальные переменные инициализируются в теле скрипта DataWeave, и на них можно ссылаться по имени только из области выражения, в которой они инициализируются.
Синтаксис для инициализации локальной переменной выглядит следующим образом: using (=) Вы можете объединить несколько определений локальных переменных в виде списка через запятую внутри функции using. Например: using (firstName = 'Annie', lastName = 'Point')
%dw 2.0
output application/json
---
using (x = 2) 3 + x
Вот пример определения локальной переменной внутри объекта:
%dw 2.0
output application/xml
---
{
person: using (user='Greg', gender='male') {
name: user,
gender: gender
}
}
Обратите внимание на это переменные ограничиваются только объектом person. Доступ к ним вне лица приведет к ошибке.
Полная документация по этому вопросу здесь: https://docs.mulesoft.com/mule-runtime/4.1/dataweave-variables
Создайте новый экземпляр и затем используйте linq отображающиеся классы вместе с отражением для копирования членских значений.
Например.
public static void CopyDataMembers(this DataContext dc,
object sourceEntity,
object targetEntity)
{
//get entity members
IEnumerable<MetaDataMember> dataMembers =
from mem in dc.Mapping.GetTable(sourceEntity.GetType())
.RowType.DataMembers
where mem.IsAssociation == false
select mem;
//go through the list of members and compare values
foreach (MetaDataMember mem in dataMembers)
{
object originalValue = mem.StorageAccessor.GetBoxedValue(targetEntity);
object newValue = mem.StorageAccessor.GetBoxedValue(sourceEntity);
//check if the value has changed
if (newValue == null && originalValue != null
|| newValue != null && !newValue.Equals(originalValue))
{
//use reflection to update the target
System.Reflection.PropertyInfo propInfo =
targetEntity.GetType().GetProperty(mem.Name);
propInfo.SetValue(targetEntity,
propInfo.GetValue(sourceEntity, null),
null);
// setboxedvalue bypasses change tracking - otherwise
// mem.StorageAccessor.SetBoxedValue(ref targetEntity, newValue);
// could be used instead of reflection
}
}
}
... или можно клонировать его с помощью DataContractSerializer:
internal static T CloneEntity<T>(T originalEntity) where T : someentitybaseclass
{
Type entityType = typeof(T);
DataContractSerializer ser =
new DataContractSerializer(entityType);
using (MemoryStream ms = new MemoryStream())
{
ser.WriteObject(ms, originalEntity);
ms.Position = 0;
return (T)ser.ReadObject(ms);
}
}
Я столкнулся с той же проблемой, и код Кристофера работал отлично, большое спасибо!
Если кому-то интересно, я немного изменил его код, так что вместо того, чтобы принимать целевую сущность в качестве параметра, он создает новый объект и возвращает его. Также я сделал параметр sourceEntity
общим:
public static T CloneEntity<T>(this DataContext dc, T sourceEntity) where T:class, new()
{
var targetEntity = new T();
//... original method code...
return targetEntity;
}
Тогда я могу сделать следующее:
dataContext.MyEntities.Attach(dataContext.CloneEntity(theEntity));
Если вы загружаете объект из DataContext, задав для ObjectTrackingEnabled значение false, вы можете вставить этот объект как новый в другой DataContext
DataContext db1 = new DataContext();
DataContext db2 = new DataContext();
db2.ObjectTrackingEnabled = false;
MyEntity entToClone = db2.Single(e => e.Id == id);
// ... change some data if it is needed
db1.MyEntities.InsertOnSubmit(entToClone);
db1.SubmitChanges();