实体框架6代码在插入

时间:2016-03-05 20:12:14

标签: c# entity-framework entity-framework-6

在不同的应用程序域之间保存实体的唯一键是否有良好的做法?

含义:

每个系统都可以有一个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生成的密钥。

有没有更好的方法来实现这一目标?

如果我忘记/错过了一些重要的代码,请告诉我,我会添加它。

感谢所有帮助者

3 个答案:

答案 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。类似的东西:

  1. 启动交易
  2. 执行插入
  3. 插入标识符
  4. 执行所需的任何操作
  5. 提交成功或在任何失败时回滚
  6. 在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应该提供额外的方法来允许自定义事务控制(BeginTransactionCommitTransaction)以及SaveChanges。不幸的是,这种方式违背了工作单元模式的目的(只是做完了事情并在完成时提交)。

    此解决方案允许更大的灵活性,但我还会在此之前调查计算列解决方案(信用转到marc_s)。我不建议使用触发器。