在不同的应用程序域之间保存实体的唯一键是否有良好的做法?
含义:
每个系统都可以有一个id为19的字母。这个带有Id 19的字母在应用程序的不同实例之间会有所不同。
应用程序的每个实例都有一个标识符。
因此,我希望在所有应用程序实例的任何位置保存唯一列。
例如,如果应用程序的前缀是:23,
所有正在运行的应用程序之间的电报的唯一键是 - 2319。
抱歉,如果我拼错了。不知道如何用专业词来定义它。
比方说我的实体模型如下:
public interface IBaseEntityObject
{
public int Id {get; set;}
}
public abstract class BaseEntityObject : IBaseEntityObject
{
[Key]
public int Id {get; set;}
}
public class Letter : BaseEntityObject
{
public string Title {get; set;}
public string Content {get; set;}
public virtual Folder Folder {get; set;}
public int FolderId {get; set;}
public DateTime CreationDate {get; set;}
public int LetterUniqueId {get; set;}
}
在我的通用存储库实现中,我有以下方法:
public T Add(T item)
{
return Context.Set<T>().Add(item);
}
我想通过Tcp / Ip向我的系统发送一封信给另一个实例。 我需要跟踪不同系统之间的字母,因为我们想要使用acks - 意思,知道这封信是否被接收,阅读等等。
// In this method I take Letter with LetterUniqueId = null
public bool SendLetter(Letter letterToSend)
{
try
{
using (var ownedUow = UowFactory())
{
var unitOfWork = ownedUow.Value;
var letters = unitOfWork.LettersRepository;
var savedLetter = letters.Add(letterToSend);
// Save changes happen here
unitOfWork.Commit();
*** // Is there a way to execute the following code automatically when adding a letter with EF? I'd pre***
// _instancePrefix is a unique number saved in configuration for every instance
savedLetter.LetterUniqueId = Convert.ToInt32(string.Format("{0}{1}", _instancePrefix, savedLetter.Id));
// Notifies EF about the update
letters.UpdateSpecificProperty(savedLetter, letter => letter.LetterUniqueId);
unitOfWork.Commit();
}
}
catch (Exception ex)
{
Log("Could not save the letter in the database", ex);
return false;
}
}
我讨厌在此事务中提交两次(保存更改两次)的事实,但这是必要的,因为我需要使用由EF生成的密钥。
有没有更好的方法来实现这一目标?
如果我忘记/错过了一些重要的代码,请告诉我,我会添加它。
感谢所有帮助者
答案 0 :(得分:0)
我认为我解决这个问题的方法是将instanceprefix保存在数据库中并像这样扩展Letter:
public static int GetUniqueId(this Letter letter)
{
return Convert.ToInt32(string.Format("{0}{1}", Letter.InstancePrefix, savedLetter.Id));
}
答案 1 :(得分:0)
我认为首先保存实体然后在同一事务中更新它有一些错误,其中一些附加值是第一次保存的结果。
可以使用序列为实体生成唯一ID。对于本机不支持序列的数据库,需要自定义实现。
答案 2 :(得分:0)
我认为另一种解决方案是控制事务并在提交之前使用生成的id。类似的东西:
在C#中,它应该如下所示:
using (var context = new CustomContext())
{
using (var dbContextTransaction = context.Database.BeginTransaction())
{
try
{
// various context operations
context.SaveChanges();
int id = insertedEntity.Id;
// do stuff with the id
dbContextTransaction.Commit();
}
catch (Exception)
{
dbContextTransaction.Rollback();
}
}
}
为了将其与工作单元模式一起使用,unitOfWork应该提供额外的方法来允许自定义事务控制(BeginTransaction
,CommitTransaction
)以及SaveChanges
。不幸的是,这种方式违背了工作单元模式的目的(只是做完了事情并在完成时提交)。
此解决方案允许更大的灵活性,但我还会在此之前调查计算列解决方案(信用转到marc_s
)。我不建议使用触发器。